I'm trying to write an Actor in Unreal Engine C++, that gets texture data from a render target.
I have an Actor class:
#include "RenderActor.h"
#include "Engine.h"
#include <stdio.h>
// Sets default values
ARenderActor::ARenderActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
UE_LOG(LogTemp, Warning, TEXT("Init RenderActor\n"));
}
// Called when the game starts or when spawned
void ARenderActor::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("BeginPlay RenderActor\n"));
UTextureRenderTarget2D* target = GetTextureByName(TEXT("MyCanvas"));
}
// Called every frame
void ARenderActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
UTextureRenderTarget2D* GetTextureByName(const TCHAR* name)
{
return LoadObject<UTextureRenderTarget2D>(NULL, name, NULL, LOAD_None, NULL);
}
int ARenderActor::GetTextureData(UTextureRenderTarget2D* TextureRenderTarget ,void* out_ptr,int length)
{
int sx=TextureRenderTarget->SizeX,sy=TextureRenderTarget->SizeY;
TArray<FColor> SurfData;
FRenderTarget *renderTarget = TextureRenderTarget->GameThread_GetRenderTargetResource();
check((sx*sy*4)<=length);
renderTarget->ReadPixels(SurfData);
memcpy(out_ptr,reinterpret_cast<void*>(SurfData.GetData()),sx*sy*4);
return sx*sy*4;
}
There is a .h below:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Runtime/Engine/Classes/Components/WindDirectionalSourceComponent.h"
#include "Runtime/Engine/Classes/Engine/WindDirectionalSource.h"
#include "Runtime/CoreUObject/Public/UObject/UObjectBaseUtility.h"
#include "Runtime/CoreUObject/Public/UObject/UObjectGlobals.h"
#include "Runtime/Engine/Classes/Engine/TextureRenderTarget2D.h"
#include "RenderActor.generated.h"
UCLASS()
class MEMRENDER_API ARenderActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ARenderActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UTextureRenderTarget2D* GetTextureByName(const TCHAR* name);
int GetTextureData(UTextureRenderTarget2D* TextureRenderTarget ,void* out_ptr,int length);
};
Now I can compile it on Ubuntu 18.04, but get a runtime error:
/home/starrabb1t/UnrealEngine/Engine/Binaries/Linux/UE4Editor: symbol lookup error: /home/starrabb1t/Documents/Unreal Projects/MemRender/Binaries/Linux/libUE4Editor-MemRender-7856.so: undefined symbol: _ZN12ARenderActor16GetTextureByNameEPKDs
P.S: I have a scene with RenderActor object. Also I created render target MyCanvas in root of content directory.
Related
I am using UnrealEngine 4.27.2. While Compiling my C++ code i am getting this error " Unknown function specifier "BluePrintImplementableEvent" after creating a UFUNCTION.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "damageableActor.generated.h"
UCLASS()
class BASICS_API AdamageableActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AdamageableActor();
UFUNCTION(BlueprintImplementableEvent, Category = "Damage")
void onTakeAttack();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
void takeAttack();
};
So I am a beginner with game programming in UE4, just starting out with c++. The code below worked perfectly before I attached a springcomponent to my mesh. This is a simple Pawn class that I created. I should also mention that once I included the spring component and tested it and it did not work, my computer shut down accidently. It give the same error repeatedly for any class I create, I have tried making a new class and applying the code.
Please see Image for the error VS 2017 gives when I try to debug
Below is the RollingStone.cpp file code.
#include "RollingStone.h"
#include "Classes/Components/InputComponent.h"
#include "Classes/GameFramework/FloatingPawnMovement.h"
#include "Classes/Camera/CameraComponent.h"
// Sets default values
ARollingStone::ARollingStone()
{
// Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
FloatingPawnMovement = CreateDefaultSubobject<UFloatingPawnMovement>("PawnMoevement");
StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>("StaticMeshComponeent");
Camera = CreateDefaultSubobject<UCameraComponent>("CameraComponeent");
Camera->SetRelativeLocation(FVector(-500.f, 0.f, 0.f));
Camera->SetupAttachment(StaticMesh);
SetRootComponent(StaticMesh);
bUseControllerRotationYaw = true;
bUseControllerRotationPitch = true;
}
// Called when the game starts or when spawned
void ARollingStone::BeginPlay()
{
Super::BeginPlay();
}
void ARollingStone::MoveForward(float Amount)
{
FloatingPawnMovement->AddInputVector(GetActorForwardVector()* Amount);
}
void ARollingStone::MoveRight(float Amount)
{
FloatingPawnMovement->AddInputVector(GetActorRightVector()* Amount);
}
void ARollingStone::Turn(float Amount)
{
AddControllerYawInput(Amount);
}
void ARollingStone::Lookup(float Amount)
{
AddControllerPitchInput(Amount);
}
// Called every frame
void ARollingStone::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void ARollingStone::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis("MoveForward", this, &ARollingStone::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &ARollingStone::MoveRight);
PlayerInputComponent->BindAxis("Turn", this, &ARollingStone::Turn);
PlayerInputComponent->BindAxis("LookUp", this, &ARollingStone::Lookup);
}
Below is the RollingStone.h file code:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "RollingStone.generated.h"
UCLASS()
class MYPROJECT_API ARollingStone : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
ARollingStone();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
void MoveForward(float Amount);
void MoveRight(float Amount);
void Turn(float Amount);
void Lookup(float Amount);
class UFloatingPawnMovement* FloatingPawnMovement;
UPROPERTY(EditAnywhere, Category = "Components")
UStaticMeshComponent* StaticMesh;
UPROPERTY(EditAnywhere, Category = "Components")
class UCameraComponent* Camera;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};
Will appreciate you taking the time to help me. I am now very sure that the accidental shutdown caused this since its not working even after I stop using the springarmcomponent, you can see it is not there in the code and this previously working code now does not even debug.
I am using visual studio 2017 by the way!
Thank you!
Looking forward to a solution.
I am currently learning Unreal and working with C++ and when creating a collision box I am receiving an 'Error C2248: 'UPrimitiveComponent::bGenerateOverlapEvents': cannot access private member declared in class 'UPrimitiveComponent'
The error is showing at line 18 in the ShipController.cpp file.
When reading around it was suggested that instead of using 'bGenerateOverlapEvents' to use 'SetGenerateOverlapEvents' instead however whilst this compiled correctly the collision box didn't not function properly.
Ship Controller Header File:
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "ShipController.generated.h"
UCLASS()
class BASICSHOOTER_API AShipController : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
AShipController();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
UPROPERTY(EditAnywhere)
UShapeComponent* CollisionBox;
UPROPERTY(EditAnywhere)
float Speed = 10.0f;
UPROPERTY(EditAnywhere, Category="Spawning")
TSubclassOf<class ABulletController> BulletBlueprint;
void Move_XAxis(float AxisValue);
void Move_YAxis(float AxisValue);
void OnShoot();
FVector CurrentVelocity;
bool Died;
UFUNCTION()
void OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
};
Ship Controller Cpp file
// Fill out your copyright notice in the Description page of Project Settings.
#include "ShipController.h"
#include "BulletController.h"
#include "EnemyController.h"
#include "Components/BoxComponent.h"
#include "Kismet/GameplayStatics.h"
// Sets default values
AShipController::AShipController()
{
// Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("Root"));
CollisionBox->bGenerateOverlapEvents = true;
CollisionBox->OnComponentBeginOverlap.AddDynamic(this, &AShipController::OnOverlap);
AutoPossessPlayer = EAutoReceiveInput::Player0;
}
// Called when the game starts or when spawned
void AShipController::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AShipController::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (!CurrentVelocity.IsZero())
{
FVector NewLocation = GetActorLocation() + Speed * CurrentVelocity * DeltaTime;
SetActorLocation(NewLocation);
}
}
// Called to bind functionality to input
void AShipController::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
InputComponent->BindAxis("MoveX", this, &AShipController::Move_XAxis);
InputComponent->BindAxis("MoveY", this, &AShipController::Move_YAxis);
InputComponent->BindAction("Shoot", IE_Pressed, this, &AShipController::OnShoot);
}
void AShipController::Move_XAxis(float AxisValue)
{
CurrentVelocity.X = AxisValue * 100.0f;
}
void AShipController::Move_YAxis(float AxisValue)
{
CurrentVelocity.Y = AxisValue * 100.0f;
}
void AShipController::OnShoot()
{
UWorld* World = GetWorld();
if (World)
{
FVector Location = GetActorLocation();
World->SpawnActor<ABulletController>(BulletBlueprint, Location, FRotator::ZeroRotator);
}
}
void AShipController::OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
if (OtherActor->IsA(AEnemyController::StaticClass()))
{
Died = true;
this->SetActorHiddenInGame(true);
UGameplayStatics::SetGamePaused(GetWorld(), true);
}
}
Enemy Controller Header File
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "EnemyController.generated.h"
UCLASS()
class BASICSHOOTER_API AEnemyController : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AEnemyController();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UPROPERTY(EditAnywhere)
UShapeComponent* RootBox;
UPROPERTY(EditAnywhere)
float Speed = -200.0f;
};
Enemy Controller Cpp File
// Fill out your copyright notice in the Description page of Project Settings.
#include "EnemyController.h"
#include "Components/BoxComponent.h"
// Sets default values
AEnemyController::AEnemyController()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
RootBox = CreateDefaultSubobject<UBoxComponent>(TEXT("Root"));
}
// Called when the game starts or when spawned
void AEnemyController::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AEnemyController::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
FVector NewLocation = GetActorLocation();
NewLocation.X += Speed * DeltaTime;
SetActorLocation(NewLocation);
if (NewLocation.X < -600.0f)
{
this->Destroy();
}
}
I expect the output to be when an object of class EnemyController touches an object of class ShipController that the game will pause and that the object of class ShipController will be hidden in game.
Using SetGenerateOverlapEvents(true); instead of bGenerateOverlapEvents = true; did work.
For some reason I had set the objects at different heights and the collision boxes were not colliding which is why it didn't appear to work.
Thanks for the comments and advice!
We tried to initialize components inside our character's constructor. The code worked on v4.15 but not v4.21.
Here is our code (.h file and .cpp file respectively):
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MainCharacter.generated.h"
UCLASS()
class VRET_API AMainCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AMainCharacter();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
private:
UPROPERTY()
class UCameraComponent * camera;
UPROPERTY()
class USceneComponent * VRroot;
};
#include "MainCharacter.h"
#include "Camera/CameraComponent.h"
#include "MotionControllerComponent.h"
#include "Runtime/Engine/Classes/Components/StaticMeshComponent.h"
#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
// Sets default values
AMainCharacter::AMainCharacter()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
VRroot = CreateDefaultSubobject<USceneComponent>(TEXT("VRroot"));
VRroot->SetupAttachment(GetRootComponent());
camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
camera->SetupAttachment(VRroot);
}
The code compiles, but when we run the game our character's components aren't being initialized and we cannot find them in the editor during gameplay BUT the default character components (eg:capsule component) work and show properly.
This happened to me. Try to unparent your blueprint class from AMainCharacter to just ACharacter, and then again parent it from AMainCharacter.
It worked for me!
class Game {
private:
string title;
bool running;
State currentState;
public:
sf::RenderWindow window;
void setup();
void run();
};
I have a variable called currentState. This is State:
#ifndef STATE_HPP
#define STATE_HPP
using namespace std;
class State {
private:
public:
void start();
void update();
void render();
};
#endif
And then I have a class called PlayState, which inherits State:
#ifndef PLAY_STATE_HPP
#define PLAY_STATE_HPP
#include <SFML/Graphics.hpp>
#include "Game.hpp"
#include "State.hpp"
using namespace std;
class PlayState : public State {
private:
sf::CircleShape shape;
Game game;
public:
PlayState();
void start();
void update();
void render();
};
#endif
On my Game.cpp, I am creating currentState, by doing:
currentState = PlayState();
The problem is, though, that it's not working. currentState.update() is state.update(). It seems that I am not overriding the State methods when I create PlayState.
Here's PlayState.cpp:
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <stdio.h>
#include "PlayState.hpp"
PlayState::PlayState() {
printf("heyyy\n");
}
void PlayState::start() {
shape.setRadius(100.f);
shape.setOrigin(20.0f, 20.0f);
shape.setFillColor(sf::Color::Green);
}
void PlayState::update() {
sf::Event event;
while (game.window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
game.window.close();
//running = false;
}
}
printf("here\n");
}
void PlayState::render() {
printf("here\n");
game.window.clear();
game.window.draw(shape);
game.window.display();
}
Any ideas about how I can 'override' those methods? Thank you.
EDIT
I had to make State.cpp functions virtual so that they can be overriden.
I also had to define State *currentState as a pointer and create PlayState with "currentState = new PlayState();".
Also, now I access .update and .draw with ->update() and ->draw().
Two problems. As #McAden said, the functions in State that are to be overridden in PlayState need to be marked virtual. The other problem is that the data member currentState in Game has type State. When you assign an object of type PlayState to it, it gets the State part of the PlayState object, but not the derived parts. This is called "slicing". To prevent it, make currentState a pointer to State, and when you create that PlayState object, assign its address to the Game object's currentState.
What you're looking for is the concept of virtual functions.
Wikipedia entry
State needs:
virtual void update();
PlayState needs:
void update();
You need to make your function's with the virtual modifier ie.
virtual void Update();
When calling currentState->Update() this will call the topmost overridden function, if you desire to call any of the parent classes functions inside of the classes methods simply specify ie. State::Update(); when calling the function.