UE4 用到什麼記錄什麼

BluePrint:html

建立Widget藍圖,編輯控件,綁定事件,根據不一樣狀況可能須要getPlayerController->setInputMode,在觀看藍圖或者gameMode藍圖內加入該widget。react

 

 

能夠用Promote to Variable產生一個隨時可使用的變量,在綁定控件時就可使用這個變量(類)中的屬性和方法,如:c++

 

 

更改Material的時候要先把普通materail轉爲Dynamic Material,而後用setParameterValue來更改它的屬性,例如如下根據電池電量改變人物顏色的例子:程序員

 

使用timeline來設置有規律的行爲,如石門平滑開啓:web

 

使用射線檢測來觸發雕塑事件(按下某鍵觸發射線檢測):編程

 

製做晝夜循環:數組

1.把lightSource改成moveableapp

2.打開關卡藍圖使用timeline實現光源旋轉,Y軸爲270~-90dom

 

也能夠用Cinematics->add Matinee來建立一些動畫,好比門的開關,人站到石臺上石臺自動升高等,先右鍵->new empty group,而後選中你要操做的物體,再在Mayinee內右鍵新建movement track或者sound track等等:若是是movemet track 則移動要操做的物體,而後在相應位置添加關鍵幀來完成動畫:編輯器

 

建立頂視角Minimap步驟:

1.在characterBlueprint頭頂上新建一個向下的相機(可能須要關閉autoActive以避免替換主相機),相機內添加組件SceneCaptureComponent2D

2.ContentBrowser右鍵material->render target 新建一個,CompressionSetting設置爲userInterface2D

3.把剛剛的render target放到SceneCaptureComponent2D的Texture Target中

4.右鍵render Target->create metarial新建一個材質,連上emmisive color會顯示的更好

5.新建widget放入image控件,Image屬性設置爲剛剛的material

6.運行

 

能夠建立接口藍圖,在裏面定義函數,讓其餘藍圖實現該接口,這樣能夠對相同事件有不一樣反饋方式,好比三個box,都是鼠標點擊,第一個放大,第二個縮小,第三個旋轉,就能夠創建鼠標點擊接口,而後三個方塊藍圖各自實現點擊效果。如下是鼠標點擊actor而後調用各actor實現的BP_pick接口的三個方法的藍圖。鼠標點擊使用射線檢測以及世界座標轉換

 

無限跑酷中建立無限地圖的方法:在一個道路塊的終點後面放置一個Arrow用來當作下一塊地塊的放置位置,並在終點附近設置Collision Box,當人物經過Collison Box使用Spawn Actor建立一個新地塊,建立的transform爲上一個地塊的Arrow的transform,並把這個地塊arrow的trasnform記錄下來爲下一個地塊使用。在construct Script內初始化必定數量的地塊。

 

建立能夠重複使用的component:(以懸浮組件爲例子,越靠近地面收到一個更大的向上力以維持懸浮)

1.父物體設爲movable

2.建立sceneComponent類命名爲HoverComponent(Actor component藍圖類和Scene component藍圖類的區別在於scene component有relative position)

3.獲取父物體的引用:

4.使用射線檢測設置反重力的方向和大小:(add damping 是增長阻力以避免越彈越高.該例子設置射線長50,離地面越近受到的力越大)

5.把該component做爲任意static mesh的子component

 

 

控制相機pitch範圍的方法:

1.

 

2.在第三人稱模板中

 

 

Lerp和Clamp的區別:

lerp的值是(1-alpha)*A+alpha*B

Clamp是輸入在範圍內輸出=輸入,輸入在範圍外輸出=邊界值

 

使用AI跟蹤玩家:建立AIcontrollerBP,在場景中添加NavMeshBoundsVolume,在AIcontroller中使用一個timer隔一段時間調用一次AIMoveTo  

添加radial force component 可使物體對其餘物體產生力的影響

Projectile movement component能夠快速模仿子彈運動

cast的時候右鍵->convert to pure cast 能夠移除順序連線接口

碰撞無效的時候記得檢查Mesh是否是包含Collision組件

使用RemoveFromParent來移除Widget,OpenLevel來打開關卡,SetGamePaused來暫停遊戲 

使用SpawnXXXAtLocation來在特定位置產生特效或聲音

Add Reroute Node 但是使藍圖看起來更整潔

實現更改遊戲速度(慢放)的效果,用exctue console command :slomo 0.5 (速度變爲0.5倍)

第一人稱射擊時鏡頭shake方法:新建類藍圖繼承camera shake,更改參數後再第一人稱藍圖內射擊後調用play world camera shake便可

使用launch character能夠從新設置character的速度,好比觸碰到某物體時向上彈起(跳跳版)

 

 

 

 

 

 

C++:

UE4 經常使用標記宏:

UCLASS():

Blueprintable:能夠把該類編程藍圖(類名右鍵)

BlueprintType:該類能夠做爲其餘藍圖類的變量使用

NotBlueprintType :不可做爲其餘藍圖變量使用

 


UPROPERTY() :
BlueprintCallable: 屬性能夠在藍圖中被調用
BlueprintReadOnly:屬性能夠被藍圖讀取,可是不可被修改
BlueprintReasWrite:屬性能夠被藍圖讀取和修改
Category: 爲屬性添加分類標籤
EditAnywhere:該屬性能夠在屬性窗口中修改
EditDefaultOnly:該屬性能夠在屬性窗口中修改,可是隻能在基類的屬性窗口修改
VisibleAnywhere:該屬性能夠在屬性窗口中看見,可是不可修改
VisibleDefaultsOnly:該屬性只可在基類的屬性窗口中看見,並且不可修改

 

 

UFUNCTION:
BlueprintCallable:該函數能夠在類藍圖或者關卡藍圖中調用
BlueprintImplementableEvent:這個函數在頭文件聲明可是應該在類藍圖或者關卡藍圖中重寫,應該和BlueprintCallable一塊兒使用這樣藍圖就能夠調用它,目的是使非程序員可針對特殊狀況(這些狀況不存在默認操做或標準行爲)建立自定義響應。範例:在宇宙飛船遊戲中玩家飛船得到強化道具時發生的事件
BlueprintNativeEvent:這個函數能夠在藍圖類中重寫,同時擁有C++實現,函數名爲FuncName_Implementation,可是調用的時候不用加implementation,和BlueprintCallable一塊兒使用以便在藍圖中調用.能夠在藍圖中使用Add Call To Parent Function調用父方法內容
BlueprintPure: 這個函數不會改變對象的數據內容,能夠用在get函數上,該函數必須有返回值
Category:爲函數添加類別標籤

 

meta說明符:
BlueprintProtected:
這個函數只能由當前對象調用,不能被其餘對象調用

 

變量類型前綴:
模板類以T爲前綴
繼承自UObject的類以U爲前綴
繼承自AActor的類以A爲前綴
繼承自SWidget的類以S爲前綴
抽象藉口類以I爲前綴
枚舉類E爲前綴
布爾變量以b爲前綴
大部分其餘類以F爲前綴,如FString,FVector

 

UE4 支持三類字符串:
FString 相似於普通字符數組,
FName是放在全局字符串表裏的,一般用來表示不可變的大小寫不敏感的字符串
FText通常是表示處理本地化的字符串
和字符串有關的API以及字符串間相互轉化:https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/StringHandling/index.html

 

 

 

如何debug:
打印到屏幕:
#include "Engine.h"
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Some debug message!"));
打印到output log:
UE_LOG(LogClass, Log, TEXT("You have collected %s"),*DebugString);

 

 

定時器
FTimerHandle VarName
GetWorldTimerManager().SetTimer(this, &AMatineeActor::CheckPriorityRefresh, 1.0f, true);
GetWorldTimerManager().ClearTimer(this, &AMatineeActor::CheckPriorityRefresh);
GetWorldTimerManager().PauseTimer()
GetWorldTimerManager().UnPauseTimer()
GetWorldTimerManager().IsTimerActive()
GetWorldTimerManager().GetTimerRate()

 

使Pawn響應玩家輸入:

AutoPossessPlayer = EAutoReceiveInput::Player0;

 

Clamp函數:把一個值規範化到一個範圍:

CurrentVelocity.Y = FMath::Clamp(AxisValue, -1.0f, 1.0f)

 

引用GameplayStatics.h以使用不少有用的函數
#include "Kismet/GameplayStatics.h"
更換攝像機視角
APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this,0)
if(camera1 = OurPlayerController->GetViewTarget() )
OurPlayerController->SetViewTarget(Camera2)
OurPlayerController->SetViewTargetWithBlend(Camera2, SmoothBlendTime)

 

建立帶有SpringArm的相機:
OurCameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));
OurCameraSpringArm->AttachTo(RootComponent); //如今用SetupAttachment
OurCameraSpringArm->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, 50.0f), FRotator(-60.0f, 0.0f, 0.0f));
OurCameraSpringArm->TargetArmLength = 400.f;
OurCameraSpringArm->bEnableCameraLag = true;
OurCameraSpringArm->CameraLagSpeed = 3.0f;
OurCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("GameCamera"));
OurCamera->AttachTo(OurCameraSpringArm, USpringArmComponent::SocketName);
帶有SpringArm的相機旋轉視角時,yaw方向能夠直接旋轉Actor,Pitch方向旋轉SpringArm,Putch旋轉時用Clamp限定旋轉角度
NewRotation.Pitch = FMath::Clamp(NewRotation.Pitch + CameraInput.Y, -80.0f, -15.0f);

 

 

視域縮放功能:
ZoomFactor = FMath::Clamp<float>(ZoomFactor, 0.0f, 1.0f);
// 基於ZoomFactor來混合相機的視域和彈簧臂的長度,Lerp把ZoomFactor映射到一個範圍內的值
OurCamera->FieldOfView = FMath::Lerp<float>(90.0f, 60.0f, ZoomFactor);
OurCameraSpringArm->TargetArmLength = FMath::Lerp<float>(400.0f, 300.0f, ZoomFactor);

 

在代碼中直接使用content browser中的素材:
static ConstructorHelpers::FObjectFinder<UParticleSystem> ParticleAsset(TEXT("/Game/StarterContent/ParticlesP_Fire.P_Fire"));
if (ParticleAsset.Succeeded())
{
OurParticleSystem->SetTemplate(ParticleAsset.Object);
}

 

代碼使用UMG:
在build.cs中:
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG" });
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
#include "Blueprint/UserWidget.h"
TSubclassOf<UUserWidget> StartingWidgetClass;
UUserWidget* CurrentWidget
CurrentWidget = CreateWidget<UUserWidget>(GetWorld(), StartingWidgetClass);
CurrentWidget->AddToViewport();

 

 

獲取必定3D空間內隨機一點:
GetWhereToSpawn()返回一個boxComponent
#include "kismet/KismetMathLibrary.h"
FVector ASpawnVolume::GetRandomPointToVolume()
{
FVector MeshOrigin = GetWhereToSpawn()->Bounds.Origin;
FVector MeshExt = GetWhereToSpawn()->Bounds.BoxExtent
return UKismetMathLibrary::RandomPointInBoundingBox(MeshOrigin, MeshExt);
}


其餘隨機函數:
FMath::FRand()
FMath::FRandRange(MinNum,MaxNum)

 

枚舉類型在UCLASS標記前聲明:
UENUM(BlueprintType)
enum class EBatteryPlayState
{
EPlaying, //能夠選擇顯示名稱放在逗號內 UMETA(DisplayName="Dance")
EGameOver,
EWon,
EUnknown
};

EBatteryPlayState status;

OR

TEnumAsByte<EBatteryPlayState> status; 

 

找到屬於某一個類的全部Actors並存入數組:
TArray<AActor*> FoundActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(),ASpawnVolume::StaticClass() , FoundActors);

 

判斷某一個變量是否是屬於某個類型只需cast一下而後看是否是空:
ASpawnVolume* TestSpawnVolume = Cast<ASpawnVolume>(myActor);
if(TestSpawnVolume!=nullptr)
{
// do something
}

找到overlap的全部Actors並存入數組,首先聲明一個USphereComponent,而後:
TArray<AActor* >OverlappedActors;
CollectionSphere->GetOverlappingActors(OverlappedActors);

PlayerCharacter裏能夠調用不少有用方法:
UGameplayStatics::GetPlayerCharacter()
MyCharacter->getMesh()
MyCharacter->getMovementComponent()

 

使用TSubclassOf
TSubclassOf<Class Type> VarName 該聲明方式聲明該變量只能賦值爲派生自Class Type的類

 

 

結構體聲明:

新建一個C++類,

#include "Chapter2.h"
       #include "ColoredTexture.generated.h"
       USTRUCT()
       struct CHAPTER2_API FColoredTexture
       {
         GENERATED_USTRUCT_BODY()
         public:
         UPROPERTY( EditAnywhere, BlueprintReadWrite, Category =
         HUD )
         UTexture* Texture;
         UPROPERTY( EditAnywhere, BlueprintReadWrite, Category =
         HUD )
         FLinearColor Color;
       };

  

 建立可重複使用component(隨機移動組件爲例):

 

#pragma once
   #include "Components/ActorComponent.h"
   #include "RandomMovementComponent.generated.h"
   UCLASS( ClassGroup=(Custom),
   meta=(BlueprintSpawnableComponent) )
   class UE4COOKBOOK_API URandomMovementComponent : public
   UActorComponent
   {
     GENERATED_BODY()public:
         URandomMovementComponent();
         virtual void BeginPlay() override;
         virtual void TickComponent( float DeltaTime, ELevelTick
         TickType, FActorComponentTickFunction* ThisTickFunction )
         override;
         UPROPERTY()
         float MovementRadius;
};
       #include "UE4Cookbook.h"
       #include "RandomMovementComponent.h"
       URandomMovementComponent::URandomMovementComponent()
       {
         bWantsBeginPlay = true;
         PrimaryComponentTick.bCanEverTick = true;
         MovementRadius = 5;
}
       void URandomMovementComponent::BeginPlay()
       {
         Super::BeginPlay();
       }
       void URandomMovementComponent::TickComponent( float
       DeltaTime, ELevelTick TickType,
       FActorComponentTickFunction* ThisTickFunction )
       {
         Super::TickComponent( DeltaTime, TickType,
         ThisTickFunction );
         AActor* Parent = GetOwner();
         if (Parent)
         {
           Parent->SetActorLocation(
           Parent->GetActorLocation() +
           FVector(
           FMath::FRandRange(-1, 1)* MovementRadius,
           FMath::FRandRange(-1, 1)* MovementRadius,
           FMath::FRandRange(-1, 1)* MovementRadius));
}
}

 

 使用委託(delegate與UFUNCTION綁定)舉例:

在gamemod投文件UCLASS前聲明:

DECLARE_DELEGATE(FStandardDelegateSignature)

FStandardDelegateSignature MyStandardDelegate; //建立委託成員變量

在另外的actor類中建立須要綁定的UFUNCTION,如「開燈」函數,在beginplay函數中獲取gamemode實例,並綁定「開燈」函數:

MyGameMode->MyStandardDelegate.BindUObject(this,&ADelegateListener::EnableLight);

在須要執行委託時,使用一下代碼執行委託:

AGameMode* GameMode = UGameplayStatics::GetGameMode(TheWorld);

AUE4CookbookGameMode * MyGameMode = Cast<AUE4CookbookGameMode>(GameMode);

MyGameMode->MyStandardDelegate.ExecuteIfBound();

使用如下代碼解除委託:

MyGameMode->MyStandardDelegate.Unbind();

使用帶參數的委託:

DECLARE_DELEGATE_OneParam(FParamDelegateSignature,FLinearColor) 其餘地方相同,調用的時候傳遞參數便可

使用廣播委託:

假設有一個TriggerVolume 來觸發委託

在gamemode 頭文件裏聲明 DECLARE_MULTICAST_DELEGATE(FMulticastDelegateSignature) 

MulticastDelegateListener 的類(燈)裏面,聲明變量:

FDelegateHandle MyDelegateHandle;

綁定委託:

MyDelegateHandle = MyGameMode->MyMulticastDelegate.AddUObject(this,&AMulticastDelegateListener::ToggleLight);

 

 

 

結束委託:

MyGameMode->MyMulticastDelegate.Remove(MyDelegateHandle);

其餘類也能夠經過使本身的方法綁定一個MyDelegateHandle來觸發相應委託,只要調用

MyGameMode->MyMulticastDelegate.Broadcast(); 全部綁定的委託都會調用

廣播委託也能夠有參數

 

委託的缺陷是須要使用第三方類來調用委託,它的執行方法是public的

Custome Event


MyTriggerVolume (觸發事件的actor)裏面聲明:

DECLARE_EVENT(AMyTriggerVolume, FPlayerEntered)第一個參數是須要調用broadcast的類,第二個參數是事件函數簽名的類名

在類中添加一個event signature:FPlayerEntered OnPlayerEntered;

在AMyTriggerVolume::NotifyActorBeginOverlap 中添加OnPlayerEntered.Broadcast(); 

 

建立一個TriggerVolEventListener 類(燈所在類),在裏面聲明:

UPROPERTY()

UPointLightComponent* PointLight;

UPROPERTY(EditAnywhere)

AMyTriggerVolume* TriggerEventSource;

UFUNCTION()

void OnTriggerEvent();

在beginplay裏面綁定事件:

TriggerEventSource->OnPlayerEntered.AddUObject(this,&ATriggerVolEventListener::OnTriggerEvent)

 

接口Interface

要在c++中使用接口,要手動建立.h 和.cpp文件,在UE4編輯器內沒法建立

//接口類
//h
#pragma once 
#include "ReactsToTimeOfDay.generated.h"
 
/* must have BlueprintType as a specifier to have this interface exposed to blueprints
   with this line you can easily add this interface to any blueprint class */
UINTERFACE(BlueprintType)
class MYPROJECT_API UReactsToTimeOfDay : public UInterface
{
    GENERATED_UINTERFACE_BODY()
};
 
class MYPROJECT_API IReactsToTimeOfDay
{
    GENERATED_IINTERFACE_BODY()
 
public:
    //classes using this interface must implement ReactToHighNoon
    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "MyCategory")
        bool ReactToHighNoon();
 
    //classes using this interface may implement ReactToMidnight
    UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "MyCategory")
        bool ReactToMidnight();
 
};
//cpp
#include "MyProject.h"
#include "ReactsToTimeOfDay.h"
 
UReactsToTimeOfDay::UReactsToTimeOfDay(const class FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
 
}
//實現接口的類:
//h
#include "ReactsToTimeOfDay.h"
#include "ASkeletalMeshActor.generated.h"
 
UCLASS()
class AFlower : public ASkeletalMeshActor,  public IReactsToTimeOfDay
{
    GENERATED_BODY()
 
public:
    /*
    ... other AFlower properties and functions declared ...
    */
 
    UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "MyCategory")
        bool ReactToHighNoon();
        virtual bool ReactToHighNoon_Implementation() override;
 
 
};
//cpp
bool AFlower::ReactToHighNoon_Implementation()
{
    //Default behaviour for how flower would react at noon
    //OpenPetals();
    //AcceptBugs();
    //...
 
    return true;
 
}
再次注意BlueprintNativeEvent是在cpp內有一個實現,函數名加implementation,藍圖內可重寫
BlueprintImplementableEvent是必須在藍圖內實現
檢查某個類是否實現了某接口,能夠有2個方法:
1.把那個類cast 成 檢查的interface,cast成功則實現了,null則沒實現
2.使用
if (SpawnedActor->GetClass()->ImplementsInterface(UMyInterface::StaticClass())) 來檢查
使用cast能夠把實現了相同接口的不一樣對象當作一類對象來使用,好比把它們放進數組
相關文章
相關標籤/搜索