Training Stream - Tanks vs. Zombies, p.3 - May 17th

Tanks3.png&stc=1

**

WHAT**
Continuing the “Tanks” C++ stream, and Lauren will be making tanks to fight a zombie onslaught, using Paper2D. This time, we’re adding the ability to aim our tank’s turret with the mouse and fire a projectile from it.

WHEN
Tuesday, May 17th @ 2:00PM-3:00PM ET - Countdown

WHERE

WHO

  • Training Content Creator - )
  • Sr Learning Resource Engineer

Feel free to ask any questions on the topic in the thread below, and remember, while we try to give attention to all inquiries, it’s not always possible to answer’s questions as they come up. This is especially true for off-topic requests, as it’s rather likely that we don’t have the appropriate person around to answer. Thanks for understanding!
**
ASSETS HERE!**](https://forums.unrealengine.com/showthread.php?111973)

Archive:

Great stuff again! Any for the code? The very last part spawning the missile isn’t working for me and I’m getting an error that the AMissile isn’t an AActor in the if statement:

       if(AMissile*NewProjectile = World->SpawnActor(Projectile))

I tried changing the header file to make it an actor but that didn’t work either. Im still pretty new to c++.

Thank you!

PS Im still not able to use the Player Start in the editor to spawn the tank in so let us know how you fixed that too!

What error are you getting? Also, did you remember to add the AMissile code to your project? And yes, we will be posting the code soon.

Most likely it was just setting the default pawn class and game mode and all of that stuff I showed in the Project Settings page. It’s really more of a question of what I forgot to do last time, as this is usually very straightforward. I just missed something, and I have forgotten exactly what it was. When the project is posted, it should work fine, I just don’t remember what I missed the first time around.

The project is now available for download in our Asset Sharing forum. The post is here:
https://forums.unrealengine.com/showthread.php?111973-Tanks!-project-from-May-17-2016-stream&p=536484#post536484

Hey

Below is the error I’m still getting (I had added the AMissile to the project). Its this line that its not happy about…if(AMissile*NewProjectile = World->SpawnActor(Projectile))

EDIT: I get error C2440: initialising: Cannot convert from AActor * to AMissile *
Note: Cast from base to derived requires dynamic cast or static cast

The download project you linked doesnt seem to have the code folder that you had before in pervious downloads which i found the most useful to compare etc. Would it be possible to add that?

D

Hi ,

First of all, thank you for doing this stream series. You and Lauren have done a fantastic job explaining Unreal’s C++ API.

A couple of things I’ve noticed:

In your ATank::Tick method, in the part that handles the tank’s rotation there is a small problem.
[FONT=Courier New]

			if (AdjustedDeltaYaw < -90.0f)
			{
				AdjustedDeltaYaw += 180.0f;
				bReverse = true;
			}
			
			else if (AdjustedDeltaYaw > 90.0f)
			{
				AdjustedDeltaYaw -= 180.0f;
				bReverse = true;
			}

Float point precision errors make these comparisons fragile. For example, when the AdjustedDeltaYaw is 90, but the float representation is slightly off (90.0000001) the tank will move in the opposite direction. We need tolerance bounds to solve the issue.

To fix the issue with TankBP not spawning at PlayerStart, I had to change the “Spawn Collision Handling Method” of TankBP to “Try To Adjust Location, But Always Spawn”. But I couldn’t figure out what I was colliding with. Do you know what is happening?

Thanks! Glad to know it’s helpful.

Do you mean that the tank will actually move the wrong direction, or that it will turn suboptimally when it’s right on the line between turning right and turning left? Depending on what the effect is, there are cases in gameplay programming where I’m OK with fragility. Usually, in engine-level programming, I would be more strict about things like that, but if it’s at a gameplay level and doesn’t lead to a bad player experience, it’s usually considered acceptable. So, the tank turning an extra 0.0000001 degrees by rotating the wrong way is OK, but the tank moving left when I press right or vibrating in place is not.

I would probably have gone with “always spawn” without the location adjustment, but the fact that it’s moving you around is interesting, because that means it’s detecting a collision, as you said, and we don’t deliberately have any collision geometry on the tank, or the land, for that matter. Maybe we need to go through the sprite components that we used to make the tank/turret/terrain and double-check that collision is turned off. That seems like it is the most probable cause of an issue like that.

Hello! I just answered your post in the other forum, but the short version is that we’ve updated the zip file with tested code, so hopefully that will fix it.

Hopefully I do not come off the wrong way, because I do not mean this in a rushing or negative way, but I was wondering if their happens to be an estimated time of Part 4 of the stream? In my Game Prototyping Class, along with my group assignment, I am following a long a tutorial series and have to turn that in, in two weeks. Doesn’t have to be completed, just have to do as much as I can, so I am just curious as to when the next part is :slight_smile: Sorry if I am not allowed to ask this!

Hi UchihaKite! Right now, we’re scheduled for 6/14 - hope to see you then!

Typically I wait until it is on Youtube, because I am usually busying doing my C++ homework, but this will defiantly be my first Stream. Looking forward to it, thank you very much for the reply!

The problem that I see is not that the tank is turning sub-optimally or incorrectly by a very small degree, it actually reverses direction. For example, when turning the tank clockwise, and logging the Yaw values as they change, the tank’s direction never gets to 90 degrees:
[FONT=Courier New]LogTemp:Warning: TankDirection->GetComponentRotation().Yaw, DesiredMovementDirection.Rotation().Yaw: (89.999992, 90.000000)
LogTemp:Warning: DeltaYaw, AdjustedDeltaYaw: (0.000008, 0.000008)
LogTemp:Warning: TankDirection->GetComponentRotation().Yaw, DesiredMovementDirection.Rotation().Yaw: (89.999992, 90.000000)
LogTemp:Warning: DeltaYaw, AdjustedDeltaYaw: (0.000008, 0.000008)
LogTemp:Warning: TankDirection->GetComponentRotation().Yaw, DesiredMovementDirection.Rotation().Yaw: (89.999992, 90.000000)
LogTemp:Warning: DeltaYaw, AdjustedDeltaYaw: (0.000008, 0.000008)

Trying to turn the tank by an additional 90 degrees results in:
[FONT=Courier New]LogTemp:Warning: TankDirection->GetComponentRotation().Yaw, DesiredMovementDirection.Rotation().Yaw: (89.999992, 180.000000)
LogTemp:Warning: DeltaYaw, AdjustedDeltaYaw: (90.000008, -89.999992)

Note how AdjustedDeltaYaw becomes negative since the difference between the tank direction and the desired direction is slightly greater than 90 degrees. I’m not sure where this small error is coming from, and how reproducible it is, but it happens consistently for me.

Thanks, disabling collision on the tank, turret and terrain fixed the spawning issue.

Hello.I have updated my engine to 4.11 .I have an error in Turret.cpp file that ParentComponentActor is not declared.Also the page for ParentComponentActor has been removed from documentation.Any help?

Hello, Freedom911. You’re right, that won’t work in 4.11 because it has been deprecated. Here’s the relevant piece of code from Actor.h:



private:
	/** The Actor that owns the UChildActorComponent that owns this Actor. */
	UPROPERTY()
	TWeakObjectPtr<AActor> ParentComponentActor_DEPRECATED;	

	/** The UChildActorComponent that owns this Actor. */
	UPROPERTY()
	TWeakObjectPtr<UChildActorComponent> ParentComponent;


Although this change takes away your ability to get your parent actor directly, you can now get the actual component that spawned you by calling GetParentComponent(). From there, you can find the actor that owns the component as usual, and that’s what we need in this turret function. Overall, this is an improvement, because you could have an actor with multiple child actor components, and you’d have to search through them if you wanted to know which one spawned you. Now, you can go directly to that component and then quickly and easily trace it back up to the parent from there. On our next stream, it is likely that we’ll go up to 4.12, in which case the next code drop will address this and any other API breaks that have happened since 4.10. Thanks for your question!

Thanks, gseben, I understand what you mean now. Yes, there’s some imprecision there, so checking the absolute value of delta against an epsilon would be a good idea to stop redundant rotator usage. To fix that, we’ll use KINDA_SMALL_NUMBER as our epsilon. We’ll also need to check if DeltaYaw is 180. To do this, we should replace this check:



			if (DeltaYaw != 0.0f)


with this:



			if (FMath::IsNearlyZero(DeltaYaw - 180.0f, KINDA_SMALL_NUMBER))
			{
				bReverse = true;
			}
			else if (!FMath::IsNearlyZero(DeltaYaw, KINDA_SMALL_NUMBER))


I hope this clears up the issue you were seeing. On my end, there was no visible defect coming from this, but rotators were being set constantly at times when it wasn’t needed and this prevents that.

Which header file would we add this change? Would it be the Turret.h one or some other header file? This is regarding the reply you made to Freedom911.

I have strange error after editing top of Tank.h it is sometimes fixable by:

but sometimes this solution do not workand I have to try random combination of it to work. Can anyone help?

Worst tutorial ever

Thanks for the tutorial, I know I am really late to the party but I’m hoping someone can still remember and help me get through my bottleneck. I am struggling to spawn a shell. In particular I can’t figure out where the shell sprite was added.

On the video at 1:14 there doesn’t seem to be any shell sprite in the blueprint but I have downloaded the C++ code and it is not in the Missile class either? I tried to add one in the construction script of RegularMissileBP and a few other things but none have worked.

Also at 1:14 there is a paper flipbook. I can make the flipbook but if I right click on the Blueprint then the only flipbook node available is AddPaperFlibookComponent. There is no SetFlipbook etc.

Thanks!

I’ve been following this series on Youtube (using 4.18.2) and have encountered a scenario I can’t quite figure out yet.

It seems my Projectile check is always returning negative and hence my UE_LOG for the fire event isn’t firing.

My turret.h contains the following:


protected:

// Maximum turn rate in degrees/second for the turret.
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Turret")
float YawSpeed;

// Tank that owns this turret.
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Turret")
ATank* Tank;

// Projectile to spawn when firing.
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Turret")
TSubclassOf<AActor> Projectile;


And turret.cpp has the following code for the the fire action:


const FTankInput& CurrentInput = Tank->GetCurrentInput();

        if (CurrentInput.bFire1)

        {

            UE_LOG(LogTemp, Warning, TEXT("FIRE! 1"));

        }

if (CurrentInput.bFire1 && Projectile)

{ 

UE_LOG(LogTemp, Warning, TEXT("FIRE! 2"));

if (UWorld* World = GetWorld())

{

UE_LOG(LogTemp, Warning, TEXT("FIRE! 3"));

if (AActor* NewProjectile = World->SpawnActor(Projectile))

{

FVector Loc = TurretSprite->GetSocketLocation("Muzzle");

FRotator Rot = TurretDirection->GetComponentRotation();


NewProjectile->SetActorLocation(Loc);

NewProjectile->SetActorRotation(Rot);

}


}

}


However **FIRE! 1 **is working fine, and shows in my logs. But Fire! 2 is not, implying the check on Projectile is failing, and I can’t figure why that would be the case here. Any ideas?