Академический Документы
Профессиональный Документы
Культура Документы
//eject mode: f8
optimize tip
PrimaryComponentTick.bCanEverTick = false, to sleep components or stop them from
take resourse
//access to pawn
//when we access to controller, that is a link between player and pawn and then
pawn
Pawn p = GetWorld()->GetFirstPlayerController().GetPawn(); //store pawn .cpp
AActor* myactor = p; //myactor in .h
/////////////////////////////////////////////////////////////////////////////
//pickup system
#define OUT
TickComponent(){
//create pawn and gameMode blueprint, why blueprint ? to prevent "hardcoding
//of changes and assets" into code
//means if we want to change name of asset then editor will track those changes
//that means we don't end up typing exact name of our modified default pawn intp
code
//if we do that and we change name in editor, then it won't be tracked
//blueprint is useful to binding assets to code
//these blueprint classes inhrit from default pawn
//hardcoding means assets writen into code,
//means we refer to something by its name and file path,
//problem is tracking asset
//"defaultPawn_bp" is a asset
//inherit from class as a blueprint/also we can inherit from class as a c++ class
//1-select "defaultPawn" in eject mode and select blueprint->convert selecyed actor
to blueprint class
//this store in "external dependency"
//2-edit shape in blueprint editor then compile and save
//3-inastate by drag into viewport
//4-create "actor component" in "c++ classes" folder
//5-add new created component to "defaultPawn_bp" in blueprint editor
//6-inherit GameMode_BP from GameMode(in c++ classes) as Blueprint, just like same
we did for "defaultPawn"
//7-in GameMode_BP, set "default pawn class" to BP_DefaultPawn that we created
//8-now in "project setting->maps & modes" set "default GameMode" to BP_GameMode
and "default Pawn class" tp BP_DefaultPawn
//now when we play game and go to eject mode, defaultPawn is BP_DefaultPawn
//what is out-parameters: function change parameters that we given and then return
them
//for example, we send a empty FVecor variable as parameter to "GetPlayerViewPoint"
and it return variable with calculate value
//parameter with perfix out_
//means void getter going to change parameters
//this is confiusing so we can use a macro to annotate these variables
//only declare this in .cpp and after #include: #define OUT
//now place OUT, befere each parameter, where thay have out_ perifx, such as
GetPlayerViewpoint
//how find parameters are out ?
//parameter identifir: out_ in
//collection of references: TArray<Actor*> &OverlapingActor
//look at method document
//11- line tracking or raycast out to reach distance(superman laser but with one
eye)
//useful for laser to track bullet path
}
//////////////////////////////////////////////////////////////////////
//convert FRotator to vector
FRotator rot; FVector vec = rot.Vector();
//get information
//1-search subject
//2- examine members after . or ->
/* FindComponentByClass()
-to find attach component
*/
UComponent* comp; //example UPhysicsHandleComponent - .h
//go to parent, in this case "defualt pawn" then find component specidied in <> -
c++
comp = GetOwner()->FindComponentByClass<UComponent>();
if(comp){}else{UE_LOG(Log_Temp, Warning, TEXT("bal"), *GetOwner()->GetName());}
/*Input Binding
-Settings->Project setting->engine->Input and map key/mouse to action/axis name
-action mapping: on/off
-axis mapping: analog
-in eject mode you can find "PawnInputComponent" in details(native component)
*/
UInputComponent* input; //holder for input - .h
input=GetOwner()->FindComponentByClass<UInputComponent>(); //find input component
at runtime - .cpp
//now we map our function to key
input->BindAction("ActionName", //key to action map in project setting
IE_Pressed, //key press action
this, //current component/class
&MyCurrentClass::MyMethod, //refrence to my method in current class to
execute when key pressed
)
/* generics
-<>
*/
//help
//search name of method in entire of solution and see examples in engine code
//google it
1757295542
5333
09387174326
9904550437
masomehmousavi4@gmail.com
/*
Exposing events to blueprint
1- convert actor to bluepoint by "settings->convert selected actor to bluepoint
class"
2- in .h of class that attached to out bluepoint, add followong code:
*/
//3- declare delegate(event) after pre-processor, #include and before class
declartion
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnOpenDoorEvent);
//4- now declure following code in .h class declaration:
public:
UPROPERTY(BlueprintAssignable)
FOnOpenDoorEvent OnOpenDoorEvent; //now event avilavle from Blueprint editor as
event
//5- now we broadcast event(call for events) in .cpp, OpenDoor() method
OnOpenDoorEvent.Broadcast();//now anythings that connect to our event in blueprint
will execute
//6- now in blueprint editor select "c++ component", rmb and select events
//7- create smooth door open/close by timeline
//create rotation
//world-space = absolut rotation: object in orgin has r{0,0,0} but when we rotate
it become r{0,0,90}
//relative = door in orgin has r{0,0,0} but when we rotate it, its rotation is
r{0,0,0} again
//so rotaion in worls is addtive but in relative not
//relative is great for components that use anywhere and in any location/rotation
in level
//1- get init rotation: BeginPlay()->GetActorRotation()->variable (blueprint
editor)
//2- open/close event->timeline->CombineRotator(MakeRotator, get_variable)-
>setActorRotation
//compile code in unreal and use "message log", it has useful info
//redline errors
//add Engine.h before generated.h
//switch to Developement_game and then back to Developement_Editor build
configuration
//rotate actors
//set "mobality" to "movable"
Rotator rot = Rotator(); //define rotation vector
GetOwner()->SetActorRotation(rot);
//create a material
//message on screen
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("This is an on screen
message!"));
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Some
variable values: x: %f, y: %f"), x, y));
//or use this MACRO at the begin of your cpp, so we can use a regular lovely
print(); inside to all
//To prevent your screen from being flooded, you can change the first parameter,
key, to a positive number. Any message printed with that key will remove any other
messages on screen with the same key. This is great for things you want to log
frequently
#define print(text) if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 1.5,
FColor::White,text)
/*
EVENT handling
-allows call member function on c++ objrcts and dynamically bind to function and
call functions on object
-degates are combination of function/variable and
-events handle by delgates
-delgates using templetes and typedefs heavy
-declare by macros and many predifined macros based on varius comination of
function signtures
so signture of function nound to macro :
*/
void foo() = DECLARE_DELEGATE(DelegateName)
void foo(ParamType param1) = DECLARE_DELEGATE_OneParam(DelegateName, Param1Type,
Param1Name)
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FActorBeginOverlapSignture, class
AActor*, OtherActor);
//compiler bound this delegate with function format below:
void MyOverlap(AActor* OtherActor)
/*FActorBeginOverlapSignature, associates a type with this delegates signature.
Delegate signatures are stored in the header files of their respective classes
and super-classes(in this case AActor)
Children can and do inherit their status with delegates from their parents.
look in the headers of base classes to find more info about delegates signatures */
//how add event handler to delegate list of callbacks
//delegate will except an event handler with same signture
//if signture has no type/name argument then function you define must also have no
argument
//first parameter is delegate signture and is a type that use in other parts of
system
//1-declare event handler(exact singture as delegate signture)in MyOverlap.h
UFUNCTION()
void OnOverlap(AActor* OtherActor)
//2-define handler in MyOverlap.cpp
void MyOverlap::OnOverlap(AActor* OtherActor){
// what happend when overlap meet
}
//3-now we add our function to delegate's list of callbacks
//this done by calling delegate's AddDynamic in MyOverlap.cpp
//first argument,"this" means reference to myslef
//secend argument is a reference to function that will called in event of event
OnActorBeginOverlap.AddDynamic(this, &MyOverlap::OnOverlap);
//wenever MyOverlap and another actor overlap, OnBeginAcorOverlap delegate which
will call
//MyOverlap::OnOverlap(AActor* OtherActor) passing in a pointer to other AActor
overlaping it
//(OtherActor)
//optimize building
project->myproject properties->nmake->addtional option = /yu
comments
-place comment on sifntures in header, when hover cursor on method in .cpp,
comments appear
great way to sure about what we did before
declare/create component
make component as root
destroy when actor overlap
make actor random scale
actor spawn
declare/create component to choose spawn actor
display only actors devired from our class
/*
1-create components, find more in engine/classes/components/
A-declare in .h file
*/
#include "Components/BoxComponent.h" // before generated.h
PROPERTY(EditAnywhere) //will be editable in detail view
UBoxComponent* box; //define box collision component
B- in .cpp
box = CreateDefaultSubobject<UBoxComponent>("box"); //create/naming component
/*
2-create overlap event
-event called when something overlap with this component as player with trigger or
object have a blocking collision(player hit wall)
A-in .cpp call function when event trigger
*/
box->onComponentBeginOverlap.addDynamic(this, &OurClassName::OnExecuteWhenOverlap);
/*
when comp in OnExecuteWhenOverlap ovelap with box comp, ovelap event trigger and
function OnExecuteWhenOverlap will be call
B-declare function in .h
*/
UFUNCTION()
void OnExecuteWhenOverlap(UPrimitiveComponent* overlappedComp,
AActor* otherActor,
UPrimitiveComponent* otherComp,
int32 otherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult)
/*
C-define function in .cpp
*/
#include "Kismet/GameplayStatics.h"
MyClass::OnExecuteWhenOverlap(as above){
//if component overlap with player?
if(otherActor == UGameplayStatics::GetPlayerCharacter(this, 0)){
Destroy(); //when overlap trigger, this fumction call and destroy
component
}
}
//UGamePlayStatics is in fact a helper class, and it contains a variety of
functions that
//you may need to call on the fly, such as spawning particles
/*
determine root component ?
1-just reorder CreateDefaultSubobject in .cpp
*/
box=CreateDefaultSubobject<>(); //box is root
mesh=CreateDefaultSubobject<>(); //static mesh is child
/* 2- using RootComponent */
RootComponent = mesh; //cancel out reorder and now mesh is root
SpawnBox->Bounds->BoundExtent),
FRotator::ZeroRotator);
}
/////////////////////////////////////////////////////////////////////////////////
actor: anything that place in 3d world
-many actors ship with engine, they are accessable from "modes"
-why we create custom actors ?
1-add functionality to existing class
2-combine components in a combination not present in default sub classes
3-add additional member variables to a class
-when inherit from actor, #include point to Actor.h, becuase new class is subclass
of actor
-UCLASS is a macro which indicate this class will be exposed to unreal reflection
system
this system allows us to inspect and iterate object properties during runtime +
manage
references to our objects for garbage collection
-MYPROJECT_API macro after class help project compile properly on windows and
ensuring
that our project's module's classes exported correctly in directlly
PrimaryActorTick.bCanEverTick=true
-implement inside of constructor
-enable ticking for this actor
-all actors have a function called Tick and "bCanEverTick" means that actor will
have
that function called once per frame and enabling actor to perform actions in every
frame
-for performance optimization, we can disiable it
/*
GameMode:
-special type of actor, map's GameMode is instantiated by engine when game starts
-is part of unreal game framework
FTransform
-by default constructed to have 0 rotation and location at Origin
-define actor location
UPROPERTY
GetWorld
-reference to current level's UWorld instance then call SpawnActor and give it
actor location
FTimerHandle
GetWorldTimerManager().SetTimer()
-call our method on object pointed by this pointer after 10 sec
-SetTimer return an object(handler) to allow us to cancel timer
-take a FTimerHandle object as reference
*/
/*UPROPERTY macro
ensuring that object declared in pointer is considered to be referenced
and won't be garbage-collected(that is, deleted) out from under us, leavng pointer
dangling*/
/*
CreateDefaultSubobject<>()
is templete based on type of object to create
first parameter is name of subobject
second is whater object should be transient(that is not saved along with parent
object)
*/
/*
//Load Assets from Actor Class Constructor
1-define following code in constructor after "CreateDefaultSubobject":
2-rmb on your asset in "Content Browser" and choise "Copy References"
then paste inside TEXT()
*/
mesh = CreateDefaultSubobject<UStaticMeshComponent>("bla");
/*
-we create an instance of "FObjectFinder" class and passing in type of asset that
-we are trying to load as a templete parameter
-FObjectFinder is a class templete that help us to load assets
-when we construct it, we pass in a string that contains a path to asset that we
are trying to load
-use auto to avoid trying out our whole object type in its declaration,
compiler deduces it for us, without auto we declare asset as :
ConstructorHelper::FObjectFinder<UStaticMesh> asset;
-"FObjectFinder" has "Object" property that will either have a pointer to asset or
NULL
if asset could not be found
*/
auto asset =
Constructor::FObjectFinder<UStaticMesh>(TEXT("StaticMesh'/Engine/BasicShapes/Cube.C
ube'"));
//string inside TEXT() is format "{ObjectType}"'/Path/To/Asset.asset'
if(asset.Object != nulptr){mesh->SetStaticMesh(asset.Object);}
/*
Implementing Actor functionality by Inheritance
-second way to implement a custom Actor
-done by make a new subclass which add member variables/functions/component to
existing Actor class
-int32: use to ensure of portability between various compilers that UE supports
-UPROPERTY: when use, variables garbage collect appropriately
-UFUNCTION:
1-can call or overridden by blueprint
2-can be marked as "exec" that means they can be run as console commands
by player/developer during play session, which enables debuging
*/
//1-inherit from "GameState" base class(content browser/file -> new c++ class)
//2-declare following code in header
public:
UFUNCTION()
void SetScore(uint32 NewScore);
UFUNCTION()
void GetScore(); //retrieve current score
private:
UPROPERTY()
int32 CurrentScore;
//define in .cpp
AMyGameState::AMyGameState(){CurrentScore = 0;} //constructor
int32 AMyGameState::GetScore(){return CurrentScore;}
void AMyGameState::SetScore(uint32 NewScore){CurrentScore = NewScore;}
/*
Attaching components to create a hierarchy
-attaching components together creates a relationship where transformations applied
/*
Creating a Custom Scene Component
-scene component is subclass of Actor
-have transform tat is relative location/rotation/scale
-like actors, aren't render themselves
-we use their transform for various things as spawning other object at fixed offset
from actor
-TSubclassOf is a template type that allows us to restrict pointer to either base
class or subclasses
also means inside editor we will get a pre-filtered list of classes to pick
*/
//1-create custom "ScenComponent" by inherit from "ActorComponent"
//2-declare following in header:
public:
UFUNCTION() void Spawn();
UPROPERTY() TSubClassOf<AActor>ActorToSpawn;
//3-implement function in .c++
void UActorSpawnComponent::Spawn(){
UWorld* World = GetWorld(); //access to our world
if(World){
//SpawnActor wants FTransform* to specify location to spawn new actor
//so this variable has current component's transform
FTransform ComponentTransform(this->GetComponentTransform());
//spawn an instance of subclass and passing address of FTransform
World->SpawnActor(ActorToSpawn, &ComponentTransform);
}
}
//4- create "Empty Actor" and add this component to it
//5-select component and in details change "ActorToSpawn"
//now whenever spawn() is called on an instance of your component
//and it will instantiate a copy of actor class specific in ActorToSpawn
/*
Creating a custom Primitive Component READ MORE 132
-are most complex type of actor component becuase they nit have transform also
rendered
*/
//1-inherit from "MeshComponent"
//2- declare in .h
UCLASS(ClassGroup=Experimental, meta=(BlueprintSpawnableComponent))
public:
virtual FPrimitiveSceneProxy* CreateSceneProxy() override;
TArray<int32> Indices;
TArray<FVector> Vertices;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Materials)
UMaterial* material = nullptr;
//implemet "CreateAceneProxy"
FPrimitiveSceneProxy* UMyMeshComponent::CreateSceneProxy(){
FPrimitiveSceneProxy* proxy = NULL;
proxy = new FMySceneProxy(this);
return proxy;
}
/*
Creating an InventoryComponent for an RPG
-enables its containing Actor to store InventoryActors in its
inventory, and place them back into the game world
*/
//1- ActorComponent called InventoryComponent
//2- add following to header
UPROPERTY()
TArray<AInventoryActor*> CurrentInventory;
UFUNCTION()
int32 AddToInventory(AInventoryActor* ActorToAdd);
UFUNCTION()
void RemoveFromInventory(AInventoryActor* ActorToRemove);
//3- implementation
int32 UInventoryComponent::AddToInventory(AInventoryActor* ActorToAdd)
{return CurrentInventory.Add(ActorToAdd);}
void UInventoryComponent::RemoveFromInventory(AInventoryActor* ActorToRemove)
{CurrentInventory.Remove(ActorToRemove);}
//4-create a new StaticMeshActor subclass called InventoryActor. Add to declaration
virtual void PickUp();
virtual void PutDown(FTransform TargetLocation);
//5-Implement the new functions
void AInventoryActor::PickUp()
{SetActorTickEnabled(false); SetActorHiddenInGame(true);
SetActorEnableCollision(false);}
void AInventoryActor::PutDown(FTransform TargetLocation)
{
SetActorTickEnabled(true);SetActorHiddenInGame(false);SetActorEnableCollision(true)
;
SetActorLocation(TargetLocation.GetLocation());}
//6-change the constructor
AInventoryActor::AInventoryActor()
:Super()
{
PrimaryActorTick.bCanEverTick = true;
auto MeshAsset =
ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("StaticMesh'/Engine/BasicShapes
/Cube.Cube'"));
if (MeshAsset.Object != nullptr)
{
GetStaticMeshComponent()->SetStaticMesh(MeshAsset.Object);
GetStaticMeshComponent()->SetCollisionProfileName
(UCollisionProfile::Pawn_ProfileName);
}
GetStaticMeshComponent()->SetMobility(EComponentMobility::Movable);
SetActorEnableCollision(true);
}
//7-add an InventoryComponent to our character so that we have an
//inventory that we can store items in. Create a new SimpleCharacter subclass
//using the editor, and add the following to its declaration