Easy Offscreen Indicator Blueprint Node

I’ve been trying to implement this into my own little project, but can’t work out how migrate it across! Can anyone offer any assistance?

reznorism - you can try the plugin-version:

https://dl.dropboxusercontent.com/u/5075634/OffscreenIndicatorPlugin.zip

I haven’t had a chance to test it on Windows yet, but there is a Windows binary, so it should work, in theory. :slight_smile:

Awesome, thank you I’ll have a look into it =) Much appreciated!

edit Hmm, can’t seem to get it to import, is there a wiki page or something about importing custom plugins? I couldn’t find one. Through the menu I could only find add new, which only let me create my own from scratch. Thanks =)

Hey @,

i’m using your C++ node into my Markable Objects System, thank again for your work. :slight_smile:

Hey, thanks for letting me know. I’ll go check it out!

Thanks for providing this, it has saved allot of headache work in terms of having to build things from the ground up. I was able to replicate this onto a character swapping system with an added character indicator, Ill provide a link to what I have been able to replicate with it after a day. Just to get this to work I was able to force myself to figure out how to get C++ coded items working in an all blueprint project.

Again thanks allot for providing this :smiley:

I managed to get this working in my current game, which is is set in space. There are some issues with it pointing to objects in an environment that has 6DOF for the player to move. Is there anything I can do to fix these sorts of things? I’m not entirely sure how to describe them. Basically if the players ship pitches forwards or backwards the indicator will pop up to the top left corner of the viewport etc. I can provide more detail/video if this is something that could be fixed. Ta!

I know exactly what you’re talking about. This is a side effect of a cheat I use to get good results for typical FPS situations where most goals are on roughly the same plane. Basically, objectives behind the actor get dropped down quite a bit to force the calculation to always put them behind.

I have an alternative algorithm I’ve been thinking about, but haven’t had time to implement. I described it earlier in the thread, but since since works for my current project, I haven’t had a lot of impetus to go back and implement the alternative approach.

Hmm interesting. I don’t suppose it’s as easy as removing the drop down in the calculation to get it working for the purpose I’m trying to make it work for haha, I might have to look up how others have done it!

Thank you @,

I made this in Blueprint based off what you did here. I’ve included it in my Market Place item, and I think it was a great addition thanks to you!

Hi ! Great job ! You are going to make plugin for ue4,9 in future ? Because i’m c++ noob and i can’t compile this :stuck_out_tongue:

This is my version (i modified it a little) and work fine on 4.9.2

.h




// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Kismet/BlueprintFunctionLibrary.h"
#include "HUDBlueprintLibrary.generated.h"

/**
 * 
 */
UCLASS()
class MOSEXAMPLE_API UHUDBlueprintLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
	
public:
	/**
	* Converts a world location to screen position for HUD drawing. This differs from the results of FSceneView::WorldToScreen in that it returns a position along the edge of the screen for offscreen locations
	*
	* @param		InLocation	- The world space location to be converted to screen space
	* @param		EdgePercent - How close to the edge of the screen, 1.0 = at edge, 0.0 = at center of screen. .9 or .95 is usually desirable
	* @outparam	OutScreenPosition - the screen coordinates for HUD drawing
	* @outparam	OutRotationAngleDegrees - The angle to rotate a hud element if you want it pointing toward the offscreen indicator, 0° if onscreen
	* @outparam	bIsOnScreen - True if the specified location is in the camera view (may be obstructed)
	*/
	UFUNCTION(BlueprintPure, meta = (WorldContext = "WorldContextObject", CallableWithoutWorldContext), Category = "HUD|Util")
		static void FindScreenEdgeLocationForWorldLocation(UObject* WorldContextObject, const FVector& InLocation, const float EdgePercent, FVector2D& OutScreenPosition, float& OutRotationAngleDegrees, bool &bIsOnScreen);

};



.cpp




// Fill out your copyright notice in the Description page of Project Settings.

#include "MOSExample.h"
#include "HUDBlueprintLibrary.h"

void UHUDBlueprintLibrary::FindScreenEdgeLocationForWorldLocation(UObject* WorldContextObject, const FVector& InLocation, const float EdgePercent, FVector2D& OutScreenPosition, float& OutRotationAngleDegrees, bool &bIsOnScreen)
{
	bIsOnScreen = false;
	OutRotationAngleDegrees = 0.f;	

	if (!GEngine) return;

	const FVector2D ViewportSize = FVector2D(GEngine->GameViewport->Viewport->GetSizeXY());
	const FVector2D  ViewportCenter = FVector2D(ViewportSize.X / 2, ViewportSize.Y / 2);

	UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject);

	if (!World) return;

	APlayerController* PlayerController = (WorldContextObject ? UGameplayStatics::GetPlayerController(WorldContextObject, 0) : NULL);

	if (!PlayerController) return;

	ACharacter* PlayerCharacter = Cast<ACharacter>(PlayerController->GetPawn());

	if (!PlayerCharacter) return;

	FVector Forward = PlayerCharacter->GetActorForwardVector();
	FVector Offset = (InLocation - PlayerCharacter->GetActorLocation()).GetSafeNormal();

	float DotProduct = FVector::DotProduct(Forward, Offset);
	bool bLocationIsBehindCamera = (DotProduct < 0);

	if (bLocationIsBehindCamera)
	{
		// For behind the camera situation, we cheat a little to put the
		// marker at the bottom of the screen so that it moves smoothly
		// as you turn around. Could stand some refinement, but results
		// are decent enough for most purposes.

		FVector DiffVector = InLocation - PlayerCharacter->GetActorLocation();
		FVector Inverted = DiffVector * -1.f;
		FVector NewInLocation = PlayerCharacter->GetActorLocation() * Inverted;

		NewInLocation.Z -= 5000;

		PlayerController->ProjectWorldLocationToScreen(NewInLocation, OutScreenPosition);
		OutScreenPosition.Y = (EdgePercent * ViewportCenter.X) * 2.f;
		OutScreenPosition.X = -ViewportCenter.X - OutScreenPosition.X;
	}

	PlayerController->ProjectWorldLocationToScreen(InLocation, OutScreenPosition);//*ScreenPosition);

	// Check to see if it's on screen. If it is, ProjectWorldLocationToScreen is all we need, return it.	
	if (OutScreenPosition.X >= 0.f && OutScreenPosition.X <= ViewportSize.X
		&& OutScreenPosition.Y >= 0.f && OutScreenPosition.Y <= ViewportSize.Y)
	{
		
		bIsOnScreen = true;
		return;
	}

	OutScreenPosition -= ViewportCenter;

	float AngleRadians = FMath::Atan2(OutScreenPosition.Y, OutScreenPosition.X);
	AngleRadians -= FMath::DegreesToRadians(90.f);

	OutRotationAngleDegrees = FMath::RadiansToDegrees(AngleRadians) + 180.f;

	float Cos = cosf(AngleRadians);
	float Sin = -sinf(AngleRadians);

	OutScreenPosition = FVector2D(ViewportCenter.X + (Sin * 180.f), ViewportCenter.Y + Cos * 180.f);

	float m = Cos / Sin;

	FVector2D ScreenBounds = ViewportCenter * EdgePercent;

	if (Cos > 0)
	{		
		OutScreenPosition = FVector2D(ScreenBounds.Y / m, ScreenBounds.Y);
	}
	else
	{		
		OutScreenPosition = FVector2D(-ScreenBounds.Y / m, -ScreenBounds.Y);
	}

	if (OutScreenPosition.X > ScreenBounds.X)
	{		
		OutScreenPosition = FVector2D(ScreenBounds.X, ScreenBounds.X*m);
	}
	else if (OutScreenPosition.X < -ScreenBounds.X)
	{		
		OutScreenPosition = FVector2D(-ScreenBounds.X, -ScreenBounds.X*m);
	}
	
	OutScreenPosition += ViewportCenter;	

}



Remember to change the include “MOSExample.h” with yours, tell me if it work for you, if not post here your error.

Thanks ! This new code run on 4.9.2 perfect !

Hey guys I seem to be having problems getting this function to show up in the editor. I make a new C++ class and copy the code into the .h and .cpp files and change the names to my project’s. The class builds with no errors but when I restart the engine I cannot find the function FindScreenEdgeLocationForWorldLocation. I have tried in the UMG blueprint and an actors blueprint with and without context sensitive checked. I have even tried rebuilding the game from the Solution Explorer in Visual Studio.

What am I doing wrong?

I was able to solve the problem by migrating all my content to a new project. The C++ class works in the new project.

I’m using this in my fighting game to represent characters off screen. For some reason if player controller with the ID 0 (P1) is destroyed and I remove his indicator from parent then controller ID 1, 2 ,3 (P2, P3, P4) have their indicators become visible until P1’s is created again on respawn. This doesn’t happen if any one else removes theirs from parents just p1

I recently created something somewhat related to this. It gets the position of the camera frustum planes centers.
I’m gonna leave it here in case someone else stumbles upon this thread and needs it.

I’ve managed to include this into my group project however I have encountered some problems. Our game allows a ship to move in all 3 Axis which causes a strange bug whereby the indicator disappears. Does anyone know what could be altered. I think it has something to do with the Z-Axis since in the C++ Function it is set to “NewInLocation.Z -= 5000;”. Any ideas?

You could start by taking that line of code out, but I think you’d hit the problem it was originally put in there to address. I’m not entirely sure the code will work for your situation. It’s only ever been tested with a more traditional character model that doesn’t rotate on the X axis.

I’ve put some thought into an alternate approach to doing this, but I haven’t really had a lot of impetus to implement it, since this works well enough for our game. One possibility might be to simply draw lines from screen center to the object, project down to screen, and figure out where it hits the screen edge. That will still give you the problem with objects behind you because there is no screen edge if you draw a line from the screen center to something directly behind you. First thing you probably need to do is figure out where you want to put the indicator for objects that are behind the player.

For human-like characters, dropping the Z puts the icon at the bottom of the screen, which feels right. The top of the screen is used for objects in front of the character, but above their field of vision, while the bottom is used for things behind. That may work for you, so you may need another approach entirely.

Just an FYI, original posters code leaks. No need for the “new” keyword there.