<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ue4 on despatches</title><link>https://icle.es/tags/ue4/</link><description>Recent content in Ue4 on despatches</description><generator>Hugo</generator><language>en</language><lastBuildDate>Fri, 20 Jun 2025 09:25:00 +0100</lastBuildDate><atom:link href="https://icle.es/tags/ue4/index.xml" rel="self" type="application/rss+xml"/><item><title>[UE4] Unreal Engine &amp;amp; miniupnp</title><link>https://icle.es/2016/02/28/ue4-unreal-engine-miniupnp/</link><pubDate>Sun, 28 Feb 2016 10:11:15 +0000</pubDate><guid>https://icle.es/2016/02/28/ue4-unreal-engine-miniupnp/</guid><description>&lt;p>This post covers how to integrate pnp into an unreal project using miniupnp.&lt;/p>
&lt;p>The first step is to clone the project from
&lt;a href="https://github.com/miniupnp/miniupnp/">github&lt;/a>&lt;/p>
&lt;p>The module that we are interested in is the miniupnpc and in that directory,
there is another directory called msvc and this contains the solution file for
Visual Studio. Open this and if you have a more recent version of visual studio
(which very likely do), it will want to upgrade everything. Let it go through
the upgrade process.&lt;/p>
&lt;p>Building the project now will most likely fail due to a missing file
miniupnpcstrings.h . This file needs to be generated and the way to do that is
to run a script in that folder called updateminiupnpstrings.sh. You will most
probably need something like &lt;a href="https://www.cygwin.com/">cygwin&lt;/a> to for this
script to work as it a &lt;a href="https://en.wikipedia.org/wiki/Unix_shell">unix shell&lt;/a> to
work&lt;/p></description><content:encoded><![CDATA[<p>This post covers how to integrate pnp into an unreal project using miniupnp.</p>
<p>The first step is to clone the project from
<a href="https://github.com/miniupnp/miniupnp/">github</a></p>
<p>The module that we are interested in is the miniupnpc and in that directory,
there is another directory called msvc and this contains the solution file for
Visual Studio. Open this and if you have a more recent version of visual studio
(which very likely do), it will want to upgrade everything. Let it go through
the upgrade process.</p>
<p>Building the project now will most likely fail due to a missing file
miniupnpcstrings.h . This file needs to be generated and the way to do that is
to run a script in that folder called updateminiupnpstrings.sh. You will most
probably need something like <a href="https://www.cygwin.com/">cygwin</a> to for this
script to work as it a <a href="https://en.wikipedia.org/wiki/Unix_shell">unix shell</a> to
work</p>
<p>Once the miniupnpcstrings.h has been generated, we also need to follow some
instructions for Unreal Engine
for <a href="https://wiki.unrealengine.com/Linking_Static_Libraries_Using_The_Build_System">Linking Static Libraries Using The Build System</a>,
particularly the section on customizations for targeting UE4 modules.</p>
<p>From the project properties page, choose configuration manager. From
the <strong>Active Solutions Platform</strong>, select new and type in or select x64 and save
it. You have to do this for only one of the projects.</p>
<p>Building of the static project will fail since it can&rsquo;t find the lib which is
now in x64Release as opposed to just Release. The exe is not required for
integrating with Unreal Engine, but if you want to complete the build, just fix
the path in Project <code>Properties -&gt; Linker -&gt; Input</code>.</p>
<p>You should choose the release build instead of the debug build and you should
now be able to build the solution from visual studio. It did pop up some
warnings for me, but the build completed successfully.</p>
<p>The rest of the instructions are from the unreal engine documentation about
integrating static libraries, starting from section about
<a href="https://wiki.unrealengine.com/Linking_Static_Libraries_Using_The_Build_System#Third_Party_Directory">Third Party Directory</a></p>]]></content:encoded></item><item><title>[UE4] Source Control</title><link>https://icle.es/2015/12/15/ue4-source-control/</link><pubDate>Tue, 15 Dec 2015 10:35:17 +0000</pubDate><guid>https://icle.es/2015/12/15/ue4-source-control/</guid><description>&lt;p>As with any software project, it is important to use some form of source control
solution. For most software projects, there are a number of good solutions out
there. However, in the world of game development, most of these are not viable
since they won&amp;rsquo;t handle binary files very well, and unreal engine (as most
games) will have a large amount of binary resources.&lt;/p>
&lt;p>Perforce is a good tool for small teams since it is free for teams with less
than 20 developers.&lt;/p></description><content:encoded><![CDATA[<p>As with any software project, it is important to use some form of source control
solution. For most software projects, there are a number of good solutions out
there. However, in the world of game development, most of these are not viable
since they won&rsquo;t handle binary files very well, and unreal engine (as most
games) will have a large amount of binary resources.</p>
<p>Perforce is a good tool for small teams since it is free for teams with less
than 20 developers.</p>
<p>Another thing that can be confusing is what files/folders to add into the source
control. Generally, we do not want to include any files which can be
auto-generated (e.g. builds) or are transient (e.g. logs). You should generally
include the following folders into source control</p>
<ul>
<li>Config</li>
<li>Content</li>
<li><code>Intermediate/ProjectFiles/&lt;projectname&gt;.vcxproj\*</code> (the .vcxproj.user file
may not be relevant if there are multiple developers)</li>
<li>Source</li>
<li><code>&lt;projectname&gt;.sln</code></li>
<li><code>&lt;projectname&gt;/.uproject</code></li>
</ul>
<p>I found it odd that the project file is in the intermediate folder since one
wouldn&rsquo;t intuitively think to include it in source control</p>
]]></content:encoded></item><item><title>[UE4] Intellisense Errors and USTRUCT</title><link>https://icle.es/2015/02/16/ue4-intellisense-errors-and-ustruct/</link><pubDate>Mon, 16 Feb 2015 16:55:32 +0000</pubDate><guid>https://icle.es/2015/02/16/ue4-intellisense-errors-and-ustruct/</guid><description>&lt;p>The Intellisense feature of Visual Studio, while useful is quite different from
the compiler and on occassion produces false positive errors. According to the
document about
&lt;a href="https://docs.unrealengine.com/latest/INT/Programming/Development/VisualStudioSetup/index.html">Setting Up Visual Studio for UE4&lt;/a>,
this can happen for few possible reason&lt;/p>
&lt;blockquote>
&lt;ul>
&lt;li>The IntelliSense compiler (EDG) is more strict than the MSVC compiler.&lt;/li>
&lt;li>Some #defines are setup differently for IntelliSense than when building
normally.&lt;/li>
&lt;li>C++ compiled by IntelliSense is always treated as 32-bit.&lt;/li>
&lt;/ul>&lt;/blockquote>
&lt;p>However, there is also the case where the Intellisense is just plain wrong.
USTRUCT() structures are just such a case. You will find that Intellisense
complains about definitions with the structures defined as USTRUCT.&lt;/p></description><content:encoded><![CDATA[<p>The Intellisense feature of Visual Studio, while useful is quite different from
the compiler and on occassion produces false positive errors. According to the
document about
<a href="https://docs.unrealengine.com/latest/INT/Programming/Development/VisualStudioSetup/index.html">Setting Up Visual Studio for UE4</a>,
this can happen for few possible reason</p>
<blockquote>
<ul>
<li>The IntelliSense compiler (EDG) is more strict than the MSVC compiler.</li>
<li>Some #defines are setup differently for IntelliSense than when building
normally.</li>
<li>C++ compiled by IntelliSense is always treated as 32-bit.</li>
</ul></blockquote>
<p>However, there is also the case where the Intellisense is just plain wrong.
USTRUCT() structures are just such a case. You will find that Intellisense
complains about definitions with the structures defined as USTRUCT.</p>
<p>This may not be a big deal, except for the fact these fales positives makes it
difficult to spot actual errors and I like to see a clean workspace with no
errors (not even false positives). Fortunately, there is a workaround. You can
include the USTRUCT definitions only if it is not being compiled by
Intellisense.</p>
<p>Fortunately, it is just the GENERATED_USTRUCT_BODY() line that is the culprit.
To get these errors to go away, instead of that single line, use the following</p>
```c++
#ifndef __INTELLISENSE__ /* Eliminating erroneous Intellisense Squigglies
*/
GENERATED_USTRUCT_BODY()
#endif
```
<p>That&rsquo;ll make those pesky squiggly lines to disappear and give you a nice clean
workspace :-D</p>
]]></content:encoded></item><item><title>[UE4] Getting Sprint to work (C++)</title><link>https://icle.es/2015/01/25/1038/</link><pubDate>Sun, 25 Jan 2015 13:29:21 +0000</pubDate><guid>https://icle.es/2015/01/25/1038/</guid><description>&lt;p>Getting Shift to sprint in the Unreal Engine 4 is very easy. There are
technically two ways of doing it.&lt;/p>
&lt;ul>
&lt;li>Change the scale down to say 0.5 and then increase it to 1.0 for sprinting&lt;/li>
&lt;li>Change the &lt;code>MaxWalkSpeed&lt;/code> for walking and sprinting.&lt;/li>
&lt;/ul>
&lt;p>I prefer the second technique because it will keep the code simple enough and
continue to function as expected with analog controllers.&lt;/p>
&lt;p>Lets start by adding the input action bindings&lt;/p></description><content:encoded><![CDATA[<p>Getting Shift to sprint in the Unreal Engine 4 is very easy. There are
technically two ways of doing it.</p>
<ul>
<li>Change the scale down to say 0.5 and then increase it to 1.0 for sprinting</li>
<li>Change the <code>MaxWalkSpeed</code> for walking and sprinting.</li>
</ul>
<p>I prefer the second technique because it will keep the code simple enough and
continue to function as expected with analog controllers.</p>
<p>Lets start by adding the input action bindings</p>
<p><code>Edit -&gt; Project Settings -&gt; Input -&gt; Bindings</code> and add an action for <strong>Sprint</strong>
with <strong>Left Shift</strong> for the key.</p>
<p>
  <img src="/assets/2015/01/Sprint%2520Keybinding.png" alt="">

</p>
<p>All the code is in the Character class.</p>
<p>Within the header file, there are two blueprint variables for the <code>WalkSpeed</code>
and <code>SprintSpeed</code> so they can be modified easily.</p>
<p>We also override the <code>BeginPlay()</code> Method. This is used to default to Walking.</p>
<p>Add the following to your character header file</p>
```cpp
/* The speed at which the character will be walking */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Character)
uint16 WalkSpeed;

/*_ The speed at which the character will be sprinting */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Character)
uint16 SprintSpeed;

virtual void BeginPlay();

protected:
/* Enables Sprinting for the character */
void EnableSprint();

/* Disables Sprinting again */
void DisableSprint();
```
<p>Add the following to the constructor so we have defaults</p>
```cpp
AMyCharacter::AMyCharacter(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer) {

    // Other code // Set the default Defaults ;-)
    WalkSpeed = 250;
    SprintSpeed = 600;

}
```
<p>Plug in the Sprint action to the methods by adding the following lines into
the <code>SetupPlayerInputComponent</code> method:</p>
```cpp
InputComponent->BindAction("Sprint", IE_Pressed, this, &AMyCharacter::EnableSprint);
InputComponent->BindAction("Sprint", IE_Released, this, &AMyCharacter::DisableSprint);
```
<p>And implement the rest of the methods</p>
```cpp
void AVSCharacter::BeginPlay() {
    // Ensure the player starts with Walking
    DisableSprint();
}

void AVSCharacter::EnableSprint() {
    CharacterMovement->MaxWalkSpeed = SprintSpeed;
    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Black, TEXT("Sprintin"));
}

void AVSCharacter::DisableSprint() {
    CharacterMovement->MaxWalkSpeed = WalkSpeed; GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Black, TEXT("Walkin"));
}
```
]]></content:encoded></item><item><title>[UE4] Getting Multiplayer Player Pawn AI Navigation to work (C++)</title><link>https://icle.es/2014/08/25/ue4-getting-multiplayer-player-pawn-ai-navigation-to-work-c/</link><pubDate>Mon, 25 Aug 2014 15:52:34 +0000</pubDate><guid>https://icle.es/2014/08/25/ue4-getting-multiplayer-player-pawn-ai-navigation-to-work-c/</guid><description>&lt;p>Unreal Engine is an awesome piece of technology making it easy to do almost
anything you might want.&lt;/p>
&lt;p>When using the Top Down view however, there is a hurdle to get over when trying
to get multiplayer to work. This is a C++ project solution to this problem based
on
a &lt;a href="https://answers.unrealengine.com/questions/34074/does-ue4-have-client-side-prediction-built-in.html">BluePrints solution&lt;/a>.&lt;/p>
&lt;p>The basic problem stems from the fact that&lt;/p>
&lt;blockquote>
&lt;p>&amp;ldquo;&lt;em>SimpleMoveToLocation&lt;/em> was never intended to be used in a network
environment. It&amp;rsquo;s simple after all ;) Currently there&amp;rsquo;s no dedicated engine
way of making player pawn follow a path. &amp;quot; (from the same page)&lt;/p>&lt;/blockquote>
&lt;p>To be able to get a working version of &lt;em>SimpleMoveToLocation&lt;/em>, we need to do the
following:&lt;/p></description><content:encoded><![CDATA[<p>Unreal Engine is an awesome piece of technology making it easy to do almost
anything you might want.</p>
<p>When using the Top Down view however, there is a hurdle to get over when trying
to get multiplayer to work. This is a C++ project solution to this problem based
on
a <a href="https://answers.unrealengine.com/questions/34074/does-ue4-have-client-side-prediction-built-in.html">BluePrints solution</a>.</p>
<p>The basic problem stems from the fact that</p>
<blockquote>
<p>&ldquo;<em>SimpleMoveToLocation</em> was never intended to be used in a network
environment. It&rsquo;s simple after all ;) Currently there&rsquo;s no dedicated engine
way of making player pawn follow a path. &quot; (from the same page)</p></blockquote>
<p>To be able to get a working version of <em>SimpleMoveToLocation</em>, we need to do the
following:</p>
<ul>
<li>Create a proxy player class (BP_WarriorProxy is BP solution)</li>
<li>Set the proxy class as the default player controller class</li>
<li>Move the camera to the proxy (Since the actual player class is on the server,
we can&rsquo;t put a camera on it to display on the client)</li>
</ul>
<p>The BP solution talks about four classes - our counterparts are as follows:</p>
<ul>
<li>BP_WarriorProxy: ADemoPlayerProxy</li>
<li>BP_WarriorController: ADemoPlayerController (Auto-created when creating a c++
top down project)</li>
<li>BP_Warrior: ADemoCharacter (Auto-created when creating a C++ top down project)</li>
<li>BP_WarriorAI: AAIController - we have no reason to subclass it.</li>
</ul>
<p>So, from a standard c++ top down project, the only class we need to add is the
ADemoPlayerProxy - so go ahead and do that first.</p>
<p>The first thing we&rsquo;ll do is rewire the ADemoGameMode class to initialise the
proxy class instead of the default MyCharacter Blueprint.</p>
```c
ADemoGameMode::ADemoGameMode(const class FPostConstructInitializeProperties&
PCIP) : Super(PCIP)
    {
    // use our custom PlayerController class
    PlayerControllerClass = ADemoPlayerController::StaticClass();

    // set default pawn class to our Blueprinted character /_ static
    ConstructorHelpers::FClassFinder<apawn>
    PlayerPawnBPClass(TEXT("/Game/Blueprints/MyCharacter"));
    if (PlayerPawnBPClass.Class != NULL)
    {
        DefaultPawnClass = PlayerPawnBPClass.Class;
    }

    DefaultPawnClass = ADemoPlayerProxy::StaticClass();
}
```
<p>Our Player Proxy class declaration</p>
```cpp
/* This class will work as a proxy on the client - tracking
   the movements of the real Character on the server side
   and sending back controls. */
UCLASS() class Demo_API ADemoPlayerProxy : public APawn
{
   GENERATED_UCLASS_BODY()
        /** Top down camera */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera) TSubobjectPtr<UCameraComponent> TopDownCameraComponent;

        /* Camera boom positioning the camera above the character */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
    TSubobjectPtr<USpringArmComponent=""> CameraBoom;

    // Needed so we can pick up the class in the constructor and spawn it elsewhere
    TSubclassOf<AActor> CharacterClass;

    // Pointer to the actual character. We replicate it so we know its
    //location for the camera on the client
    UPROPERTY(Replicated) ADemoCharacter* Character;

    // The AI Controller we will use to auto-navigate the player AAIController\*
    PlayerAI;

    // We spawn the real player character and other such elements here virtual void
    BeginPlay() override;

    // Use do keep this actor in sync with the real one void Tick(float DeltaTime);

    // Used by the controller to get moving to work void MoveToLocation(const
    ADemoPlayerController* controller, const FVector& vector);
};
```
<p>and the definition:</p>
```cpp
#include "Demo.h"
#include "DemoCharacter.h"
#include "AIController.h"
#include "DemoPlayerProxy.h"
#include "UnrealNetwork.h"

ADemoPlayerProxy::ADemoPlayerProxy(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{
    // Don't rotate character to camera direction
    bUseControllerRotationPitch = false;
    bUseControllerRotationYaw = false;
    bUseControllerRotationRoll = false;

    // It seems that without a RootComponent, we can't place the Actual Character easily
    TSubobjectPtr<UCapsuleComponent> TouchCapsule = PCIP.CreateDefaultSubobject<ucapsulecomponent>(this, TEXT("dummy"));
    TouchCapsule->InitCapsuleSize(1.0f, 1.0f);
    TouchCapsule->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    TouchCapsule->SetCollisionResponseToAllChannels(ECR_Ignore);
    RootComponent = TouchCapsule;

    // Create a camera boom... CameraBoom =
    PCIP.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 = PCIP.CreateDefaultSubobject<UCameraComponent>(this, TEXT("TopDownCamera"));
    TopDownCameraComponent->AttachTo(CameraBoom, USpringArmComponent::SocketName);
    TopDownCameraComponent->bUseControllerViewRotation = false; // Camera does not rotate relative to arm

    if (Role == ROLE_Authority)
    {
        static ConstructorHelpers::FObjectFinder<UClass> PlayerPawnBPClass(TEXT("/Game/Blueprints/MyCharacter.MyCharacter_C"));
        CharacterClass = PlayerPawnBPClass.Object;
    }

}

void ADemoPlayerProxy::BeginPlay()
{
    Super::BeginPlay();
    if (Role == ROLE_Authority)
    {
        // Get current location of the Player Proxy
        FVector Location = GetActorLocation(); FRotator Rotation = GetActorRotation();

        FActorSpawnParameters SpawnParams;
        SpawnParams.Owner = this;
        SpawnParams.Instigator = Instigator;
        SpawnParams.bNoCollisionFail = true;

        // Spawn the actual player character at the same location as the Proxy
        Character = Cast<ADemoCharacter>(GetWorld()->SpawnActor(CharacterClass, &Location, &Rotation, SpawnParams));

        // We use the PlayerAI to control the Player Character for Navigation
        PlayerAI = GetWorld()->SpawnActor<AAIController>(GetActorLocation(), GetActorRotation()); PlayerAI->Possess(Character);
    }

}

void ADemoPlayerProxy::Tick(float DeltaTime) {

    Super::Tick(DeltaTime);
    if (Character)
    {
        // Keep the Proxy in sync with the real character
        FTransform CharTransform = Character->GetTransform();
        FTransform MyTransform = GetTransform();

        FTransform Transform;
        Transform.LerpTranslationScale3D(CharTransform, MyTransform, ScalarRegister(0.5f));

        SetActorTransform(Transform);

} }

void ADemoPlayerProxy::MoveToLocation(const ADemoPlayerController* controller, const FVector& DestLocation)
{
    /** Looks easy - doesn't it.

    - What this does is to engage the AI to pathfind.
    - The AI will then "route" the character correctly.
    - The Proxy (and with it the camera), on each tick, moves to the location of the
      real character
    -
    - And thus, we get the illusion of moving with the Player Character */

      PlayerAI->MoveToLocation(DestLocation);
}

void ADemoPlayerProxy::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const
{

    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    // Replicate to Everyone
    DOREPLIFETIME(ADemoPlayerProxy, Character);
}
```
<p>We&rsquo;ll now cover changes to the Player Controller. We&rsquo;ll rewire it here to ask
the proxy to move, which will in turn ask the AIController to find a path and
move the real player character.</p>
<p>This involves changing the <code>SetMoveDestination</code> method to call a server side
method to move the character. When the character moves, the player Proxy will
automatically mirror the movements.</p>
<p>In the header file, add the following function</p>
```cpp
/*_ Navigate player to the given world location (Server Version) */
UFUNCTION(reliable, server, WithValidation) void
ServerSetNewMoveDestination(const FVector DestLocation);
```
<p>Now let&rsquo;s implement it (DemoPlayerController.cpp):</p>
```
bool ADemoPlayerController::ServerSetNewMoveDestination_Validate(const FVector
DestLocation)
{
    return true;
}

/* Actual implementation of the ServerSetMoveDestination method */
void ADemoPlayerController::ServerSetNewMoveDestination_Implementation(const
FVector DestLocation)
{
    ADemoPlayerProxy* Pawn = Cast<ademoplayerproxy>(GetPawn());
    if (Pawn)
    {
        UNavigationSystem* const NaDemoys = 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 (NaDemoys && (Distance > 120.0f))
        {
            //NaDemoys->SimpleMoveToLocation(this, DestLocation);
            Pawn->MoveToLocation(this, DestLocation);
        }
    }

}
```
<p>And finally, the rewiring of the original method:</p>
```cpp
void ADemoPlayerController::SetNewMoveDestination(const FVector DestLocation)
{
    ServerSetNewMoveDestination(DestLocation);
}
```
<p>Finally, in terms of the character class, the only change is really to remove
the camera components that we moved to the Player Proxy which I shall leave to
you :-p</p>]]></content:encoded></item></channel></rss>