Download

Draw Debug Lines Between Actors In An Array

Hello,

I recently successfully compiled my simple plugin and began creating classes for my tool. However I am at a point where I have a class that takes an array of another class and I would like to see a visual debug connection from the first element in the array to the last. The part marked in red I want to call the OSMNodeActor class getActorLocation function but I do not know how to do such a thing.

OSMNodeActor.cpp


// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
 
#include "OSMRoadEditorPrivatePCH.h"
#include "OSMNodeActor.h"
 
AOSMNodeActor::AOSMNodeActor(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
	UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
	RootComponent = SphereVisual;
	static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("StaticMesh'/Game/FirstPersonBP/Meshes/MapPin.MapPin'"));
	if (SphereVisualAsset.Succeeded())
	{
		SphereVisual->SetStaticMesh(SphereVisualAsset.Object);
		SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, 100.0f));
		SphereVisual->SetWorldScale3D(FVector(0.8f));
	}

	NodeID = "NULL";
	NodeLocation = GetActorLocation();
	
 
}

OSMWayActor.h


// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
 
#pragma once
 

#include "OSMRoadEditorPrivatePCH.h"
#include "OSMWayActor.generated.h"
 
/**
 * 
 */
class AOSMNodeActor;

UCLASS()
class OSMROADEDITOR_API AOSMWayActor : public AActor
{
	GENERATED_BODY()
public:

		AOSMWayActor(const FObjectInitializer& ObjectInitializer);
		void DrawDebugLines();

	UPROPERTY(EditAnywhere, Category = "Way Properties")
		//Street Name
		FName WayName;
	UPROPERTY(EditAnywhere, Category = "Way Properties")
		//Whether or not to draw Debug Lines.
		bool DrawLines;
	UPROPERTY(EditAnywhere, Category = "Way Properties")
		//Nodes that Make Up This Way.
		TArray<AOSMNodeActor*> NodesInThisWay;
	
		

};




OSMWayActor.cpp


// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
 
#include "OSMRoadEditorPrivatePCH.h"
 

class AOSMNodeActor;

AOSMWayActor::AOSMWayActor(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{

	WayName = "NULL";
	NodesInThisWay.Init(0);
	DrawLines = false; 

	if (DrawLines == true){

		AOSMWayActor::DrawDebugLines();
	}
	
}



void AOSMWayActor::DrawDebugLines(){
if (NodesInThisWay.Num() != 0 && NodesInThisWay.Num() < 1){

		for (int32 i = 0; i <= NodesInThisWay.Num(); i += 2){
		
			[COLOR="#FF0000"]FVector LinkStart = GetActorLocation();
			FVector LinkEnd = GetActorLocation();[/COLOR]
			//if (!LinkStart) continue;
			//if (!LinkStart->IsValidLowLevel()) continue;
			
	DrawDebugLine(
		GetWorld(),
		LinkStart,
		LinkEnd,
		FColor(255, 0, 0),
		true, -1, 0,
		12.333
		);
	}
	}



}

You are using a TArray, so you can use an iterator which gives you the current actor.

Put your start vector outside the loop, and update after each iteration. When you draw a line, check it wasnt the first iteration…

The code below should do what you want, but is untested.



 FVector LinkStart = FVector::ZeroVector;

for (auto Itr(NodesInThisWay.CreateIterator()); Itr; Itr++)
{
    AOSMNodeActor* currNode = cast<AOSMNodeActor*>(Itr);

    FVector LinkEnd = currNode->GetActorLocation();

			
    if (LinkStart != FVector::ZeroVector) {
	DrawDebugLine(
		GetWorld(),
		LinkStart,
		LinkEnd,
		FColor(255, 0, 0),
		true, -1, 0,
		12.333
		);
	}
    }
    LinkStart = LinkEnd;
}


Geeky, that seems like reasonable code, however the cast<AOSMNodeActor*>(Itr); bit did not work so I changed it to Itr; thinking that might fix it and LinkStart = LinkEnd; was called outside of the scope that it was declared in so I moved that up one bracket. After all of that it does not work still…
looks like the cast should read AOSMNodeActor
currNode = cast<AOSMNodeActor>(*Itr); but that still does not do the trick.

Edit: it tells me that cast is an undeclared identifier and that I can not use <AOSMNodeActor> as it is illegal.

Try



for (AOSMNodeActor* Actor : nodesinthisway)
	{
		Actor->GetLocation();
	}


this version will iterate and cast at the same time

yeah but how do I mix that into the code you gave me previously?

Just replace the for loop again…

Note there is one less closing bracket now, I had a syntax error in the code I put up before.



FVector LinkStart = FVector::ZeroVector;

for (AOSMNodeActor* currNode : NodesInThisWay)
{

    FVector LinkEnd = currNode->GetActorLocation();

			
    if (LinkStart != FVector::ZeroVector) {
	DrawDebugLine(
		GetWorld(),
		LinkStart,
		LinkEnd,
		FColor(255, 0, 0),
		true, -1, 0,
		12.333
		);
    }
    LinkStart = LinkEnd;
}


I did exactly as you have there, and still no line draw between items in the array, now this array is initialized to zero at the start of running the editor and I add my own items to the array afterwards so I am wondering if that might cause the lines not to show.

Yep. That’d do it. Call your function in a tick or after the array has some data.

trying data now, need to learn tick as I attempted it with the tick that I wrote and it crashed the engine.

Hmm, its crashing without the tick now. Yay.

Yes if I initialize the array with anything other then 0 it crashes…

https://docs.unrealengine.com/latest/INT/API/Runtime/Core/Containers/TArray/Init/1/index.html

You’ve created an array of 0 elements with unitialized data. You haven’t added any nodes for the debug loop to run through, so it will crash because the data is null.

Start writing your code to add the real nodes into the TArray (using add or addunique). I cant believe you’d want them hard coded, so I assume you are building up to a system that allows you to add nodes on into a map.

This is my understanding of adding an actor class to my array, I am definitely missing something…

NodesInThisWay.Add(AOSMNodeActor, 1);

We’d need to see your new code but I’d guess you are still trying to add a class rather than an instance

If you created an instance you will have used the spawn function.

Thanks for your help Geeky, I have been able to get the DrawDebugLines function to work with preset vectors, and was able to figure out how to load an instance of my NodeActor into my array at begin play, however I would like to load the array in the engine as soon as the WayActor is is placed in the editor viewport.