• (转载)UE4 C++编程常用知识点总结


    1,给角色添加组件:
          UCameraComponent* Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera0"));
    2,字符串组合(蓝图中组合字符串):
       BuildString, string +int/float/Object/vector2/boolean……+ string
    3.将属性公开到编辑器(UE4 Doc)
      UPROPERTY(EditAnyWhere,BlueprintReadWrite,Category="Damage")
      UPROPERTY(BlueprintReadOnly,VisibleAnywhere,Transient,Category="Damage")
      VisibleAnywhere标记意为在编辑器中可见,但不能进行编辑
      Transient意为无法从硬盘保存或加载,它应该为派生的非持久值
      用于编辑器属性值的状态更新:
      PostInitProperties()函数
      #if WITH_EDITOR
      PostEditChangeProperty(FPropertyChangeEvent& PropertyChangedEvent)
      {
      }
      #endif
      UE4中蓝图中显示C++函数:
      UFUNCTION(BlueprintCallable,Category="Damage")
      C++/蓝图混合实现同一种函数:
      UFUNCTION(BlueprintNativeEvent,Category="Damage")
      void CalledFromCpp();
      CalledFromCpp_Implementation()
      {
      }
      当你创建的类不是继承自Actor时,要找到你创建的UCLASS,你必须关掉Class Viewer中的过滤器中的Actors Only(默认的情况下是被检测的,也就是说会过滤掉非继承自Actor的自定义UCLASS)。--摘选自Cookbook
      用FStringAssetReferences 和 StaticLoadObject加载资源也是一种选择方式
      可以通过全局函数ConstructObject<> 或者NewObject<>来创建继承自UObject的类
      UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=UClassNames)
      TSubclassOf<UUserProfile> UPBlueprintClassName;
      ObjectType* object = ConstructObject<ObjectType>(UClassReference);
      例如:
      AChapterGameMode *gm = Cast<AChapterGameMode>(GetWorld()->GetAuthGameMode());
      if(gm)
      {
         UUserProfile* object = ConstructObject<UUSerProfile>(gm->UPBlueprintClassName);
      }
      //NewObject用法
      UProfile* object = NewObject<UProfile>(GetTransientPackage(),uclassReference);
      删除一个非使用的UObject:
       objectInstance->ConditionalBeginDestroy();
       强制GC进行资源回收的方式:
       GetWorld()->ForceGarbageCollection(true)
       结构体的写法:
       #pragma once
       #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;
      }
      枚举的写法:
     
    UENUM()
    enum Status
    {
    Stopped UMETA(DisplayName = "Stopped"),
    Moving UMETA(DisplayName = "Moving"),
    Attacking UMETA(DisplayName = "Attacking"),
    };
    使用方法:
     UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=Status)
    TEnumAsByte<Status> status;
    继承自Actor的类使用NewObject<>和SpawnActor<>方式进行实例化,例如:
    UAction* action = NewObject<UAction>(GetTranientPackage(),UAction::StaticClass());
    UObject类的回收(你也可以通过设置引用计数为0的方式来达到释放的目的):
    UObject *o  = NewObject<UObject>(……);
    o->ConditionalBeginDestory();
    或者通过:
    GetWorld->ForceGarbageCollection(true);
    的方式也可以达到同样的目的。
    UObject和它的派生类(创建的任何东西NewObject或ConstructObject)不能使用TSharedPtr!
    TSharedPtr,TSharedRef,TWeakPtr,TAutoPtr基本使用方法:
    class MyClass{}
    TSharedPtr<MyClass> sharedPtr(new MyClass());
    weak pointers 与 shared pointers之间有一些不同,弱指针没有能力保留对象的内存当引用计数到0时
    弱指针的好处是它回收内存后,指针的引用会变成NULL,可以通过检测弱指针是否可用来进一步处理:
    if(ptr.IsValid())
    {
    }
    那些继承自UObjects的类不能使用TSharedRef
    TScopedPointer<AWarrior>warrior(this);
    TScopedPointer在作用域内避免被销毁的指针类型,也是通过引用计数的方式来进行管理的
     
    生成继承自Actor的对象,例:
    SpawnActor = GetWorld()->SpawnActor<AChapter04Actor>(AChapter04Actor::StaticClass(),SpawnLocation);
    定时器的基本使用方法:
    FTimerHandle Timer;
    GetWorldTimerManager().SetTimer(Timer,this,&AUE4GameMode::DestroyActorFunction,10);
    设置对象的生命周期可以对Actor进行销毁控制:
    SetLifeSpan(10);
    初始化物体组件:
    auto MeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("Static Mesh'/Engine/BasicShapes/Cube.Cube'"));
    if(MeshAsset.Object!=nullptr)
    {
    Mesh->SetStaticMesh(MeshAsset.Object);
    }
    需要在头文件中加入:
    #include “ConstructorHelpers.h”
     
    Debug信息到屏幕上:
    GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Red,
    FString::Printf(TEXT("%s left me"), *(OtherActor-
    >GetName())));
     
    1、委托写法(无参):
    DECLARE_DELEGATE(FStandardDelegateSignature)
     
    定义成员:
    FStandardDelegateSignature  MyStandardDelegate;
     
    绑定:
    MyStandardDelegate.BindUObject(this,&ADelegateListener::EnableLight);
    简单的C++类对象函数绑定要用BindRaw
    静态函数的绑定:BindStatic
    执行:
    MyStandardDelegate.ExecuteIfBound();
     
    解除当前的绑定:
    MyStandardDelegate.Unbind();
     
    2、委托写法(含参):
    DECLARE_DELEGATE_OneParam(FParamDelegateSignature,FLinearColor)
    DECLARE_EVENT( OwningType, EventName )
    创建一个事件。
    DECLARE_EVENT_OneParam( OwningType, EventName, Param1Type )
    创建带一个参数的事件。
    DECLARE_EVENT_TwoParams( OwningType, EventName, Param1Type, Param2Type )
    创建带两个参数的事件。
    DECLARE_EVENT_<Num>Params( OwningType, EventName, Param1Type, Param2Type, ...)
    创建带 N 个参数的事件。
     
    添加成员:
    FParamDelegateSignature MyParamDelegate;
     
    绑定:
    同无参绑定类似
     
    执行:
    MyParamDelegate.ExecuteIfBound(FLinearColor)
     
    3,多播委托的写法:
    DELCARE_MULTICAST_DELEGATE(FMulticastDelegateSignature)
     
    添加成员到指定的类中:
    FMulticastDelegateSignature FMultiDelegate;
     
    绑定类似:
    FMultiDelegate->AddUObject(this,AMulticastDelegateListener::ToggleLight);
     
    执行:
    FMultiDelegate->Broadcast();
     
    解除绑定:
    FMultiDelegate->Remove(AMulticastDelegateListener::ToggleLight);
    DECLARE_MULTICAST_DELEGATE[_Const, _RetVal, etc.]( DelegateName )
    创建一个多播的多播代理。
    DECLARE_DYNAMIC_MULTICAST_DELEGATE[_Const, _RetVal, etc.]( DelegateName )
    创建一个动态的多播代理。
    DECLARE_DYNAMIC_MULTICAST_DELEGATE[_Const, _RetVal, etc.]( DelegateName )
    创建一个封装的动态多播代理。
     
    4,自定义事件:
    DECLARE_EVENT(AMyTriggerVolume,FPlayerEntered)
     
    定义:
    FPlayerEntered OnPlayerEntered;
     
    执行:
    OnPlayEntered.Broadcast();
    绑定:
    OnPlayEntered.AddUObject(this,&ATriggerVolEventListener::OnTriggerEvent);    
    获取当前关卡中所有的指定类型AActor:
     UGameplayStatics::GetAllActorsOfClass(const UObject* WorldContextObject, TSubclassOf<AActor> ActorClass, TArray<AActor*>& OutActors)
    例如: 
    TArray<AActor*> TimeOfDayHandlers;
    UGameplayStatics::GetAllActorsOfClass(GetWorld(), ATimeOfDayHandler::StaticClass(), TimeOfDayHandlers);
    UE4定时器的使用方法:
    FTimerHandle MyTimer;
    GetWorld()->GetTimerManager().SetTimer(MyTimer,this,&APickupSppawner::SpawnPickup,10,false);
    UE4中的迭代器的用法:
    AActor的迭代器位于“EngineUtil.h”头文件中,基本使用方法:
    for(TActorIterator<AActor> It(GetWorld(),AActor::StaticClass());It;++It)
    {
       AActor* Actor = *It;
       IMyInterface* MyInterfaceInstance = Cast<IMyInterface>(Actor);
       if(MyInterfaceInstance)
       {
          MyInterfaceInstances.Add(MyInterfaceInstance); 
       }
    }
    给指定的静态网格物体组件附加默认模型文件:
    auto MeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("Static Mesh'/Engine/BasicShapes/Cube.Cube'"));
    if(MeshAsset.Object!=nullptr)
    {
       MyMesh->SetStaticMesh(MeshAsset.Object);
    }
    UINTERFACE(meta=(CannotImplementInterfaceInBlueprint)) 可解决与接口方法UNFUNCTION(BlueprintCallable)的冲突问题
    如果非实现的方法,可以在函数里写入unimplemented();比如说接口的方法。
     
    暴露接口供蓝图使用:
     
    首先,在接口中声明函数(当然为了避免蓝图可继承错误,需要借助上面的元数据声明,函数必须为虚函数,这个是从一个帖子上看到的,https://www.2cto.com/kf/201608/532601.html
    UFUNCTION(BlueprintCallable,Category = Test)
    virtual void OnPostBeginPlay();
    接着可以在cpp文件中实现该函数,
    其他的继承用法和常规C++实现方式类似,就不记录了。
     
    接口在蓝图中的实现:
    主要的声明部分:
    UFUNCTION(BlueprintImplementableEvent,BlueprintCallable,Category=AttackAvoider)
    void AttackInComing(AActor* AttackActor);
     
    蓝图中覆盖C++中实现的接口函数:
    主要的声明部分;
     UFUNCTION(BlueprintNativeEvent,BlueprintCallable,Category=Wearable)
    void OnEquip(APawn* Wearer);
    函数的主体部分:
    void IWearable::OnEquip_Implementation(APawn* Wearer)
    {
    }
     
    继承子类的写法:
    virtual void OnEquip_Implementation(APawn* Wearer) override
    {
       IWearable::OnEquip_Implementation(Wearer);
    }
     
    C++调用蓝图实现的接口:
     
    基本是通过<IInterface>::Execute_<FunctionName>的方式完成调用的
     
    继承自UObject的对象可以通过声明UCLASS(BlueprintType)的方式来让蓝图识别并作为变量使用
    UCLASS(Blueprintable)可以让蓝图继承该类
    可以同时用UCLASS(Blueprintable,BlueprintType)的方式让该类即能作为蓝图变量使用又能作为可继承的基类使用
     
    声明方法为UFUNCTION(BlueprintImplementableEvent)可以在蓝图中实现该事件并进行调用
     
    向蓝图中暴露多播委托
    首先声明一个多播委托:
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnKingDeathSignature,AKing*,DeathKing);
     
    其次在类中声明委托变量:
    UPROPERTY(BlueprintAssignable)
    FOnKingDeathSignatrue OnKingDeath;
     
    函数中调用:
    OnKingDeath.Broadcast(this);
     
     
    在蓝图可以挂在当前的多播事件,并通过调用OnKingDeath.Broadcast的函数完成调用
    解绑绑定的函数,可以通过UnBind系列的函数完成
     
    枚举在蓝图中的公开及使用:
    1, UENUM(BlueprintType)
          enum TreeType{Tree_Poplar,Tree_Spruce,Tree_Eucalyptus,Tree_Redwood};
    2,在类中的声明:
         UPROPERTY(BlueprintReadWrite)
         TEnumAsByte<TreeType> Type;
     
    属性在细节面板中可见性及修改的控制:
            UPROPERTY(EditDefaultsOnly) //默认蓝图类列表中细节属性可修改
                  bool EditDefaultsOnly;
           UPROPERTY(EditInstanceOnly)//实例化的蓝图类的细节列表中可修改
                  bool EditInstanceOnly;
           UPROPERTY(EditAnywhere) //以上两者都能进行修改
                  bool EditAnywhere;
           UPROPERTY(VisibleDefaultsOnly)//可见性控制,默认蓝图类列表中可见
                  bool VisibleDefaultsOnly;
           UPROPERTY(VisibleInstanceOnly)//实例化的细节列表中可见
                  bool VisibleInstanceOnly;
           UPROPERTY(VisibleAnywhere)//以上两者皆可见
                  bool VisibleAnywhere;
    属性在蓝图中调用及修改的基本控制:
         UPROPERTY(BlueprintReadWrite,Category=Cookbook)//读写
         bool ReadWriteProperty;
         UPROPERTY(BlueprintReadOnly,Category=Cookbook)//读
         bool ReadOnlyProperty;
     
    C++中添加蓝图中的Construction事件脚本:
    virtual void OnConstruction(const FTransform& Transform) override;
    主要在该函数中完成。
     
     
    创建一个新的编辑器模块:
    1,在你的UE4 项目中的uproject文件中找到Module模块配置参数:加上实例类似的内容(一个完整的模块配置参数):
    {"Name":"UE4CookBookEditor","Type":"Editor","LoadingPhase":"PostEngineInit","AdditionalDependencies":["Engine","CoreUObject"]}
    2,在你的项目源码目录文件夹中创建一个新的文件夹命名为:UE4CookBookEditor,并添加文本配置文件:UE4CookBookEditor.Build.cs
    3,在文本配置文件中添加以下代码:
    using UnrealBuildTool;
    public class UE4CookBookEditor : ModuleRules
    {
        public UE4CookBookEditor(TargetInfo Target)
        {
            PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore","RHI", "RenderCore", "ShaderCore" });
            PublicDependencyModuleNames.Add("CookBook");
            PrivateDependencyModuleNames.AddRange(new string[] { "UnrealEd"});
        }
    }
    4,创建基本组件模块的头文件:UE4CookBookEditor.h和UE4CookBookEditor.cpp实现文件,他们的具体内容如下:
    //头文件内容
    #pragma once
    #include "Engine.h"
    #include "ModuleManager.h"
    #include "UnrealEd.h"
    class UE4CookBookEditorModule:public IModuleInterface
    {
    };
    //实现文件的具体内容
    #include "UE4CookBookEditor.h"
    IMPLEMENT_GAME_MODULE(FUE4CookBookEditorModule,UE4CookBookEditor)
    关闭VS,右键点击你的UE项目,选择Generate Visual Studio Project files文件
    新添加的模块是不支持热更新的,就像运行时代码一样,如果你得到一个编译错误,其中提到了对生成的头文件的更改,只需关闭编辑器,然后从IDE中重新构建。
     
    自定义资源类型的写法:
    1,首先建立一个资源类,继承自UObject,例如:
    #pragma once
    #include "Object.h"
    #include "MyCustomAsset.generated.h"
    UCLASS()
    class COOKBOOK_API UMyCustomAsset :public UObject
    {
           GENERATED_BODY()
    public:
           UPROPERTY(EditAnywhere, Category = "Custom Asset")
                  FString Name;
    };
    2,创建继承自UFactory的自定义资源工厂,并重写创建函数FactoryCreateNew:
    #pragma once
    #include "Factories/Factory.h"
    #include "CustomAssetFactory.generated.h"
    UCLASS()
    class COOKBOOK_API UCustomAssetFactory :public UFactory
    {
           GENERATED_BODY()
    public:
           UCustomAssetFactory();
           virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags,UObject* Context, FFeedbackContext* Warn, FName CallingContext) override;
    };
    3,实现文件:
    #pragma once
    #include "CustomAssetFactory.h"
    #include "CookBook.h"
    #include "MyCustomAsset.h"
    UCustomAssetFactory::UCustomAssetFactory() :Super()
    {
           bCreateNew = true;
           bEditAfterNew = true;
           SupportedClass = UMyCustomAsset::StaticClass();
    }
    UObject* UCustomAssetFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName,EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext)
    {
           auto NewObjectAsset = NewObject<UMyCustomAsset>(InParent,InClass,InName,Flags);
           return  NewObjectAsset;
    }
    4,别忘了添加模块引用 “UnrealEd",否则会出现链接错误!
     
    UE4中关于文件读取的一些内容:
    判定当前文件是否存在以及文件大小的本地化方式存储在头文件一下头文件中:
    Runtime/Core/Public/GenericPlatform/GenericPlatformFile.h
    Runtime/Core/Public/HAL/PlatformFilemanager.h
    如果你想得到文件的大小,你可以这样做:
    FPlatformFileManager::Get().GetPlatformFile().FileSize(*MyFilePath);//当然你也可以直接调取GenericPlathformFile.h头文件来完成,只不过通过FPlatformFileManager可以通过一层单例模式获取
    如果你要写文件读取相关的内容,你可以通过以下头文件和模块找到你想要的头文件:
    #include "Paths.h" #include "Http.h"  
    FPlatformFileManager::Get().GetPlatformFile()下拥有打量的文件操作函数,其中包括,增删文件夹,创建文件,修改内容,移动文件,查询文件大小等
    程序中控制鼠标的显示:
    GetWorld()->GetFirstPlayerController()->bShowMouseCursor=true;
     
    UE4 Log相关
    UE_Log(LogTemp,Warning,TEXT("Message %d"),1);
    自定义Log:
    首先打开项目头文件:
    包含Engine头文件#include“Engine.h”
    DECLARE_LOG_CATEGORY_EXTERN(LogCustom,Log,All);
    第一个参数:CategoryName:Log的名称
    第二个参数:DefaultVerbosity:自定义的Log打印输出信息
    第三个参数:CompileTimeVerbosity:这是对编译后的代码进行烘焙后的一段代码(有道翻译,没理解什么意思)
     
    Message Log相关:
    #define LOCTEXT_NAMESPACE "CustomLogMessage"
    extern FName LoggerName;
    extern FMessageLog Logger;
     
    #define FTEXT(x) LOCTEXT(x,x)
    FName LoggerName("CustomLog")
    FMessageLog CreateLog( FName name )
    {
    FMessageLogModule& MessageLogModule =
    FModuleManager::LoadModuleChecked<FMessageLogModule>
    ("MessageLog");
    FMessageLogInitializationOptions InitOptions;
    InitOptions.bShowPages = true;// Don't forget this!
    InitOptions.bShowFilters = true;
    FText LogListingName = FTEXT( "Chapter 12's Log Listing"
    );
    MessageLogModule.RegisterLogListing( LoggerName,
    LogListingName, InitOptions );
    }
    AChapter12GameMode::AChapter12GameMode()
    {
    //这个没有测试,估计是上面函数的调用,可能要改成CreateLog(LoggerName);
    CreateLogger( LoggerName );
    // Retrieve the Log by using the LoggerName.
    FMessageLog logger( LoggerName );
    logger.Warning(
    FTEXT( "A warning message from gamemode ctor" ) );
    }
     
    调用
    Logger.Info(FTEXT("Info Log"));
    Logger.Warning(FTEXT("Warning Log"));
    Logger.Error(FTEXT("Error Log"));
    FMessageLog( LoggerName ).Info( FTEXT( "An info message") );
    屏幕输出信息:
    #include“Engine.h”
    GEngine->AddOnScreenDebugMessage(-1,5.f,FColor::Red,TEXT("Send your Message to Screen!"));
     
    旋转角的知识点:
    FRotator(FVector);
    FQuat(FVector Axis,float AngleRed); //四元数,FVector指的是旋转轴,angleRed指的是旋转的角度
     
    GameplayAbilities插件:
    实用的技能插件,可以在相关的博客上具体的学习一下
     
    UE4中嵌入Content内容的方式:
    可以通过快捷方式添加命令的形式实现,比如:
    mklink /j  F:UE4ProjectCookBookShowLink  F:ShowLink
     
  • 相关阅读:
    nyoj 230/poj 2513 彩色棒 并查集+字典树+欧拉回路
    nyoj 211 Cow Contest
    nyoj 203 三国志 dijkstra+01背包
    nyoj 170 网络的可靠性
    nyoj 120 校园网络
    nyoj 115 城市平乱 dijkstra最短路
    nyoj 42 一笔画问题 欧拉路径
    nyoj 38 布线问题
    hdu 2089 不要62--数位dp入门
    nyoj 712 探 寻 宝 藏--最小费用最大流
  • 原文地址:https://www.cnblogs.com/wodehao0808/p/8340329.html
Copyright © 2020-2023  润新知