Module System Help

Hello all, I am working on a system that takes two modules (blueprints with attachment points to show where other modules can connect) and snaps one to the other. This system will be used to generate a dynamic level. Connecting modules works great right now. My problem is that the way the system works right now, modules spawn in place of each other. Before I move on, here’s an idea of what I am doing:

  1. Create four variables: ‘Starting Module’ - takes a class; used to specify the first module that should be spawned, ‘Module Classes’ - an array of classes; used to hold all possible options for module spawning, ‘Module References’ - an array of Modules; used to keep track of spawned modules, and ‘Maximum Module Count’ - an integer; represents the amount of modules that should be spawned.
  2. Spawn the first module (using ‘Starting Module’) and add it to ‘Module References’.
  3. Enter a For loop starting at 1 and ending at ‘Maximum Module Count’.
  4. Get the last module spawned from ‘Module References’ (Module References[Array Index - 1]) and store it in a local variable called ‘Last Module’.
  5. Choose a random class from ‘Module Classes’ and spawn an actor using it.
  6. Snap the new actor to ‘Last Module’.
  7. Check to see if any of the attachment points on the new actor are colliding with anything (because ‘Spawn Even If Colliding’ doesn’t work).
  8. If not, add the module to ‘Module References’ and continue. If they are colliding with something, destroy the new actor and go back to Step 5. This should keep repeating until none of the attachment points collide with other objects.

This should form a level and while it works rarely, most of time it spawns modules in place of each other. For example:

In the diagram below, each number represents a module and the order they were spawned in. ‘X’ is where two modules are spawned in the same location and as a result, causes problems.

diagram1.png

This is why step 7 was added in, though it doesn’t seem to solve it. In Step 7, I check to see if any of the attachment points on the new actor are colliding with anything (because ‘Spawn Even If Colliding’ doesn’t work). This is a function that returns a bool.



bool AModule::Check()
{
     bool Result = true;
     TArray<USceneComponent*> AttachmentPoints = GetAttachmentPoints();

     for (int32 i = 0; i < AttachmentPoints.Num(); ++i)
     {
          if (!Result)
              continue;

          USceneComponent* Point = AttachmentPoints*;

          if (!IsValid(Point))
              continue;

          if (GetWorld()->LineTraceTest(Point->GetComponentLocation(), Point->GetComponentLocation() + (Point->GetForwardVector() * 50), ECC_Visibility, FCollisionQueryParams(true))
              Result = false;
     }

     return Result;
}


How this was supposed to work is:

If module 7 is a left turn which results in the module 8 colliding with module 2, module 8 will be destroyed and a new module class will be picked for module 7 (hopefully not a left turn). This should keep repeating until the new module doesn’t collide. In the end, the diagram ends up looking like this:

diagram2.png

As you can see, the path from the last diagram (7-9) doesn’t intersect path 1-3. This is what I am trying to achieve. I’m not exactly sure about what’s wrong with my solution. Any help? Thanks! :slight_smile:

The first thing that comes to mind is your collision settings - have you verified that your LineTrace actually does intersect your objects? You could try adding a DrawDebugLine to visualise that it’s in the correct spot.

Hello, I actually switched to the trace to a overlap test that ignores the new module since I’ve posted this. I have verified that the sphere trace is intersecting. Yet, I still get overlaps. So perhaps, the way I am doing it is not the best way. What would you do to achieve what I’m trying to achieve? Thanks! :slight_smile:

Can you post your new code?



bool AModule::Check(AModule* LastModule)
{
	bool Result = true;
	TArray<USceneComponent*> Points = GetAttachmentPoints();

	FCollisionQueryParams Params(true);
	Params.AddIgnoredActor(this);
	Params.AddIgnoredActor(LastModule);

	for (int32 i = 0; i < Points.Num(); ++i)
	{
		if (!Result)
			continue;

		USceneComponent* Point = Points*;

		if (!IsValid(Point))
			continue;

		if (GetWorld()->OverlapTest(Point->GetComponentLocation(), FQuat::Identity, ECC_Visibility, FCollisionShape::MakeSphere(200), Params))
			Result = false;
	}

	return Result;
}


At this stage I’m guessing, but it would be good to know if your OverlapTest ever returns positive - maybe set up a dummy run that should be positive. If it’s not then I suspect it is due to your collision settings on either the modules or the channel you’re passing to the OverlapTest.

I haven’t used OverlapTest, but it may require both actors to have Generate Overlap Events set to true.

Hey, I checked the OverlapTest and it does return positive. I think the problem is that I am going about this the wrong way, so I’ve decided to scrap my generation code and rewrite it. I am now trying to figure out a better way to put my modules together to form a level. Any idea? Thanks! :slight_smile:

I actually think the idea you had is a good one - spawn something and if it intersects undo it and try something else. If your intersections are working correctly, then the bug must be somewhere else.

The only other option I can suggest is to use some sort of 2D array to keep track of what is where, and use that instead of traces/overlap tests.

Hey, sorry it took so long to reply. I finally had some more time to work on it and I have something that gives decent results:

The problem is that if the amount of tiles I want to spawn is over or equal to 80 and press play, Unreal freezes for a bit then exits PIE which is weird. How I have the system setup is I coded my module methods (snapping, retrieving attachment points, etc.) in C++ same as before, but I handle the placement and spawning of the modules in a blueprint.






This however still has problems. I wonder how the team of Monstrum accomplished this. That is a perfect example of what I’ve been trying to do forever. It’s pretty impressive in my opinion.

It looks like they did something similar to what I’ve done except their solution actually works. :smiley: I think I’m going to go back to drawing board. How would you create a procedural level like this? Any ideas? Thanks! :slight_smile:

Found this: http://forums.tigsource.com/index.php?PHPSESSID=6564b38438d0034416f8db8e02d050a9&topic=41609.msg1036448#msg1036448

I had an idea that used a grid (even wrote a GridComponent) so I’m going to try that out real fast and get back with some results.

I finally figured it out! After trying tons of different things, an idea came to me last night. Rather than attempting to rotate the actor in the world to make thing match up, I just rotated everything in the blueprint! It now works great! :slight_smile: The only thing I need to fix is my Check function so there’s no infinite loop.