UE4 用到什么记录什么

BluePrint:

创建Widget蓝图,编辑控件,绑定事件,根据不同情况可能需要getPlayerController->setInputMode,在观看蓝图或者gameMode蓝图内加入该widget。

 

 

可以用Promote to Variable产生一个随时可以使用的变量,在绑定控件时就可以使用这个变量(类)中的属性和方法,如:

 

 

更改Material的时候要先把普通materail转为Dynamic Material,然后用setParameterValue来更改它的属性,例如以下根据电池电量改变人物颜色的例子:

 

使用timeline来设置有规律的行为,如石门平滑开启:

 

使用射线检测来触发雕塑事件(按下某键触发射线检测):

 

制作昼夜循环:

1.把lightSource改为moveable

2.打开关卡蓝图使用timeline实现光源旋转,Y轴为270~-90

 

也可以用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可以把实现了相同接口的不同对象当做一类对象来使用,比如把它们放进数组


 

 

 

 

转载于:https://www.cnblogs.com/yang-xiong/p/6392350.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值