4
\$\begingroup\$

All player controllers in the C++ game templates are not for strategy games. They all implemented so the player controls just one character. I'm not sure what approach to take when you want to control several units.

What comes in mind: The player should not have a mesh. He should be always in the center of the screen, he will never move. mouse will then control selection/edge-pan instead of him moving.

In the following image, I have a sphere, that's a "Planet", I wish to accomplish that the player to control the planet, produce units, and control them. I'm very new to UE4, using version 4.6.1, any help would be appreciated as I found little in other places.

enter image description here

Here's my current implementation. it's just the default top down template:

// StrategyAlphaCharacter.h
#pragma once
#include "GameFramework/Character.h"
#include "StrategyAlphaCharacter.generated.h"

UCLASS(Blueprintable)
class AStrategyAlphaCharacter : public ACharacter
{
    GENERATED_BODY()

    /** Top down camera */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    class UCameraComponent* TopDownCameraComponent;

    /** Camera boom positioning the camera above the character */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    class USpringArmComponent* CameraBoom;


public:
    AStrategyAlphaCharacter(const FObjectInitializer& ObjectInitializer);

    /** Returns TopDownCameraComponent subobject **/
    FORCEINLINE class UCameraComponent* GetTopDownCameraComponent() const { return TopDownCameraComponent; }
    /** Returns CameraBoom subobject **/
    FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
};


// StrategyAlphaCharacter.cpp
#include "StrategyAlpha.h"
#include "StrategyAlphaCharacter.h"

AStrategyAlphaCharacter::AStrategyAlphaCharacter(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    // Set size for player capsule
    GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);

    // Don't rotate character to camera direction
    bUseControllerRotationPitch = false;
    bUseControllerRotationYaw = false;
    bUseControllerRotationRoll = false;

    // Configure character movement
    GetCharacterMovement()->bOrientRotationToMovement = true; // Rotate character to moving direction
    GetCharacterMovement()->RotationRate = FRotator(0.f, 640.f, 0.f);
    GetCharacterMovement()->bConstrainToPlane = true;
    GetCharacterMovement()->bSnapToPlaneAtStart = true;

    // Create a camera boom...
    CameraBoom = ObjectInitializer.CreateDefaultSubobject<USpringArmComponent>(this, TEXT("CameraBoom"));
    CameraBoom->AttachTo(RootComponent);
    CameraBoom->bAbsoluteRotation = true; // Don't want arm to rotate when character does
    CameraBoom->TargetArmLength = 800.f;
    CameraBoom->RelativeRotation = FRotator(-60.f, 0.f, 0.f);
    CameraBoom->bDoCollisionTest = false; // Don't want to pull camera in when it collides with level

    // Create a camera...
    TopDownCameraComponent = ObjectInitializer.CreateDefaultSubobject<UCameraComponent>(this, TEXT("TopDownCamera"));
    TopDownCameraComponent->AttachTo(CameraBoom, USpringArmComponent::SocketName);
    TopDownCameraComponent->bUsePawnControlRotation = false; // Camera does not rotate relative to arm

}

// StrategyAlphaPlayerController.cpp
#include "StrategyAlpha.h"
#include "StrategyAlphaPlayerController.h"
#include "AI/Navigation/NavigationSystem.h"

AStrategyAlphaPlayerController::AStrategyAlphaPlayerController(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    bShowMouseCursor = true;
    DefaultMouseCursor = EMouseCursor::Crosshairs;
}

void AStrategyAlphaPlayerController::PlayerTick(float DeltaTime)
{
    Super::PlayerTick(DeltaTime);

    // keep updating the destination every tick while desired
    if (bMoveToMouseCursor)
    {
        MoveToMouseCursor();
    }
}

void AStrategyAlphaPlayerController::SetupInputComponent()
{
    // set up gameplay key bindings
    Super::SetupInputComponent();

    InputComponent->BindAction("SetDestination", IE_Pressed, this, &AStrategyAlphaPlayerController::OnSetDestinationPressed);
    InputComponent->BindAction("SetDestination", IE_Released, this, &AStrategyAlphaPlayerController::OnSetDestinationReleased);

    // support touch devices 
    InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AStrategyAlphaPlayerController::MoveToTouchLocation);
    InputComponent->BindTouch(EInputEvent::IE_Repeat, this, &AStrategyAlphaPlayerController::MoveToTouchLocation);
}

void AStrategyAlphaPlayerController::MoveToMouseCursor()
{
    // Trace to see what is under the mouse cursor
    FHitResult Hit;
    GetHitResultUnderCursor(ECC_Visibility, false, Hit);

    if (Hit.bBlockingHit)
    {
        // We hit something, move there
        SetNewMoveDestination(Hit.ImpactPoint);
    }
}

void AStrategyAlphaPlayerController::MoveToTouchLocation(const ETouchIndex::Type FingerIndex, const FVector Location)
{
    FVector2D ScreenSpaceLocation(Location);

    // Trace to see what is under the touch location
    FHitResult HitResult;
    GetHitResultAtScreenPosition(ScreenSpaceLocation, CurrentClickTraceChannel, true, HitResult);
    if (HitResult.bBlockingHit)
    {
        // We hit something, move there
        SetNewMoveDestination(HitResult.ImpactPoint);
    }
}

void AStrategyAlphaPlayerController::SetNewMoveDestination(const FVector DestLocation)
{
    APawn* const Pawn = GetPawn();
    if (Pawn)
    {
        UNavigationSystem* const NavSys = GetWorld()->GetNavigationSystem();
        float const Distance = FVector::Dist(DestLocation, Pawn->GetActorLocation());

        // We need to issue move command only if far enough in order for walk animation to play correctly
        if (NavSys && (Distance > 120.0f))
        {
            NavSys->SimpleMoveToLocation(this, DestLocation);
        }
    }
}

void AStrategyAlphaPlayerController::OnSetDestinationPressed()
{
    // set flag to keep updating destination until released
    bMoveToMouseCursor = true;
}

void AStrategyAlphaPlayerController::OnSetDestinationReleased()
{
    // clear flag to indicate we should stop updating the destination
    bMoveToMouseCursor = false;
}
\$\endgroup\$
4
\$\begingroup\$

Have you taken a look at the official UE4 Tower Defense sample/tutorial?

That sample demonstrates a UE4 project where the player is not associated with any one in-game character, instead providing building orders and high-level AI directives.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.