c++初始化camera ue4 位置_c++ vector 数组初始化 c++11 - CSDN
  • 那么,还是新建C++类 命名为CameraDirector 在CameraDirector.h中输入:UPROPERTY(EditAnywhere) AActor*CameraOne;UPROPERTY(EditAntwhere) AActor*CameraTwo;float TimeToNextCameraChange;在CameraDirector.cpp...

    那么,还是新建C++类
    这里写图片描述

    命名为CameraDirector
    这里写图片描述

    在CameraDirector.h中输入:
    
    UPROPERTY(EditAnywhere)
    AActor*CameraOne;
    
    UPROPERTY(EditAntwhere)
    AActor*CameraTwo;
    
    float TimeToNextCameraChange;

    这里写图片描述

    在CameraDirector.cpp中输入:

    include “Kismet/GamePlayStatics.h”

    在文件的最开始部分

    接着,在ACameraDirector::Tick中添加:

    const float TimeBetweenCameraChanges = 2.0f;
    const float SmoothBlendTime = 0.75f;
    TimeToNextCameraChange -= DeltaTime;
    if (TimeToNextCameraChange <= 0.0f)
    {
        TimeToNextCameraChange += TimeBetweenCameraChanges;
    
        //搜寻处理玩家控制的Actor
        APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);
        if (OurPlayerController)
        {
            if ((OurPlayerController->GetViewTarget() != CameraOne) && (CameraOne != nullptr))
            {
                //立即切换到相机1
                OurPlayerController->SetViewTarget(CameraOne);
            }
            else if ((OurPlayerController->GetViewTarget() != CameraTwo) && (CameraTwo != nullptr))
            {
                //平滑的切换到相机2
                OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime);
            }
        }
    }
    

    这里写图片描述
    完成后按F5执行。

    以上代码可以在相机1与相机2之间进行切换,接下来需要在编辑器中进行一些设置。

    1,获取PlayerController,APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);

    2,获取当前视窗对象,OurPlayerController->GetViewTarget()

    3,设置平滑过渡到新的目标视窗,OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime);

    4,设置新的目标视窗,OurPlayerController->SetViewTarget(CameraOne);

    展开全文
  • UE4这篇官方文档大体上讲解了UE4本身的诸多特性以及如何编写基本的C++代码,对理解UE4的编程基础内容非常有帮助,还是因为没有对于的汉语翻译。所以,这里我把这篇文档翻译出来,之后还会简洁的对其进行必要的总结。...

    这篇文章开始写的时间比较早,当时还没有官方翻译,不过现在大家可以直接到官方文档查看该文章的汉语翻译了

    UE4这篇官方文档大体上讲解了UE4本身的诸多特性以及如何编写基本的C++代码,对理解UE4的编程基础内容非常有帮助,但是没有对应的汉语翻译。所以,我把这篇文档翻译出来,之后还会对其进行必要的总结。由于内容比较多,会分两个部分进行编写,持续更新~



    Unreal C++ is Awesome!(虚幻4的C++是了不起的)

    This guide is about learning how to write C++ code in Unreal Engine. Do not worry, C++ programming in Unreal Engine is fun, and actually not hard to get started with! We like to think of Unreal C++ as "assisted C++", because we have so many features to help make C++ easier for everyone.

    Before we go on, it is really important that you are already familiar with C++ or another programming language. This page is written with the assumption that you have some C++ experience, but if you know C#, Java, or JavaScript, you should find many aspects familiar.

    If you are coming in with no programming experience at all, we have got you covered also! Check out our Blueprint Visual Scripting guide and you will be on your way. You can create entire games using Blueprint scripting!

    It is possible to write "plain old C++ code" in Unreal Engine, but you will be most successful after reading through this guide and learning the basics about the Unreal programming model. We will talk more about that as we go along.

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    这篇编程指导是讲解如何在虚幻引擎书写C++代码的。并不用担心,虚幻引擎中的C++编程会比你想象的要有趣的多,而且上手难度也并不大。我们认为虚幻的C++是“自动协助的C++”,因为我们有许多让C++用起来更简单的特性来给大家去使用。

    在开始前,你应该至少熟悉C++或者其他任何一门语言,这是非常重要的。这篇文档就假设你有一些C++的编程经验 ,不过如果你了解C#,java或者JavaScript,你也会发现他们都是想相通的。

    如果你之前一点编程经验都没有,那我们也替你考虑到了!去查看一下 蓝图可视化指导(Blueprint Visual Scripting guide),你也可以开始你的UE4旅程了。你完全可以使用UE4提供的蓝图功能做一款游戏,不需要写一行代码!

    在UE引擎里面你可以写原生的C++代码,但是一旦你浏览过这篇文档并学会了UE引擎里的编程模型,你就会收获的更多。接下来我们会讲解更多的内容。

    C++ and Blueprints

    Unreal Engine provides two methods, C++ and Blueprints Visual Scripting, to create new gameplay elements. Using C++, programmers add the base gameplay systems that designers can then build upon or with to create the custom gameplay for a level or the game. In these cases, the C++ programmer works in their favorite IDE (usually Microsoft Visual Studio, or Apple's Xcode) and the designer works in the Unreal Editor's Blueprint Editor.

    The gameplay API and framework classes are available to both of these systems, which can be used separately, but show their true power when used in conjunction to compliment each other. What does that really mean, though? It means that the engine works best when programmers are creating gameplay building blocks in C++ and designers take those blocks and make interesting gameplay.

    With that said, let us take a look at a typical workflow for the C++ programmer that is creating building blocks for the designer. In this case, we are going to create a class that is later extended via Blueprints by a designer or programmer. In this class, we are going to create some properties that the designer can set and we are going to derive new values from those properties. The whole process is very easy to do using the tools and C++ macros we provide for you.

    虚幻引擎提供两种方式两种方式来创建游戏元素,分别是C++和可视化蓝图。使用C++,程序员可以创建一个游戏系统来让设计者在上面给游戏关卡构建或创建游戏内容。这样,C++程序员就可以在他们最喜欢的IDE(一般是Visual Studio和Xcode)里工作,而设计师只在虚幻编辑器里面操作就好了。

    游戏里面的API以及框架相关的类在这两个系统都可以获取到,你可以分开来使用,但是当你将这两个系统结合的时候你才会真正的体会虚幻的强大所在。那么这意味着什么?当程序员创建了游戏的C++代码块并提供给设计师来制作丰富有趣的游戏时,才能发挥虚幻引擎的真正优势。

    既然已经整体的介绍了C++模块,不妨让我们看看C++程序员给设计师创建游戏模块的一个工作流程。这样,我们会创建一个类并让设计师或程序员通过蓝图对其进行扩展。接下来,我们会创建一些属性,设计师可以设置这些属性并产生一些新的值。使用引擎提供的工具和C++的宏,整个流程其实非常简单。

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Class Wizard(类向导)

    First thing we are going to do is use the class wizard within the Unreal Editor to generate the basic C++ class that will be extended by Blueprints later. The image below shows the wizard’s first step where we are creating a new Actor.

    第一件要做的事就是使用虚幻编辑器来说来生成C++的类并在之后用蓝图去拓展。这个图片展示了创建一个新的Actor(后面会介绍Actor,也可以参考链接:UE4碰撞规则详解 的第一条)的第一步。

    image alt text

    The second step in the process tells the wizard the name of the class you want generated. Here's the second step with the default name used.

    第二步是在流程中告诉向导你想要生成的类名。下面是步骤二,使用了默认的名称。

    image alt textOnce you choose to create the class, the wizard will generate the files and open your development environment so that you can start editing it. Here is the class definition that is generated for you. For more information on the Class Wizard, follow this link.

    一旦你选择了创建类,向导就会生成文件并且打开你的开发环境来让你进行编辑。下面是引擎生成类的定义如果想知道更多关于类向导的内容,点击这个链接link.

    #include "GameFramework/Actor.h"
    #include "MyActor.generated.h"
    
    UCLASS()
    class AMyActor : public AActor
    {
        GENERATED_BODY()
    
    public: 
        // Sets default values for this actor's properties
        AMyActor();
        // Called when the game starts or when spawned
        virtual void BeginPlay() override;
    
        // Called every frame
        virtual void Tick( float DeltaSeconds ) override;
    };

    The class wizard generates your class with BeginPlay() and Tick() specified as overloads. BeginPlay() is an event that lets you know the Actor has entered the game in a playable state. This is a good place to initiate gameplay logic for your class. Tick() is called once per frame with the amount of elapsed time since the last call passed in. There you can do any recurring logic. However if you do not need that functionality, it is best to remove it to save yourself a small amount of performance. If you remove it, make sure to remove the line in the constructor that indicated ticking should occur. The constructor below contains the line in question.

    类的向导给你的类生成了BeginPlay()Tick()两个重载函数(分别在游戏开始和每帧循环时调用)。BeginPlay()是触发一个事件,让你知道角色刚刚进入了游戏模式。这个位置很适合你的类来初始化一些数据与逻辑。Tick()就是在上次调用过后每过一小段时间来触发的帧循环事件在这里你可以做任何的循环逻辑处理。不过如果你不需要这两个功能,你可以移除这这个函数并保存为自己的风格。如果你移除了他,确保你移除了构造函数内设置循环是否开启的语句。下面的构造函数包含了问题中描述的这个开关。

    AMyActor::AMyActor()
    
    {
    
        // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you do not need it.
    
        PrimaryActorTick.bCanEverTick = true;
    
    }

    Making a property show up in the editor(生成一个显示在编辑器的属性

    We have our class created, so now let us create some properties that can be set by designers in the Unreal Editor. Exposing a property to the editor is quite easy using our special macro, UPROPERTY(). All you have to do is use the UPROPERTY(EditAnywhere) macro before your property declaration as seen in the class below.

    我们现在已经创建了自己的类,接下来要创建一些可以在虚幻编辑器设置的一些属性。通过使用引擎提供的宏( UPROPERTY())来将一个属性显示在编辑器其实很简单。你所需要做的就是将宏 UPROPERTY(EditAnywhere) 声明在属性的前面。

    UCLASS()
    class AMyActor : public AActor
    {
        GENERATED_BODY()
    
        UPROPERTY(EditAnywhere)
        int32 TotalDamage;
    
        ...
    };

    That is all you need to do to be able to edit that value in the editor. There are more ways to control how and where it is edited. This is done by passing more information into the UPROPERTY() macro. For instance, if you want the TotalDamage property to appear in a section with related properties, you can use the categorization feature. The property declaration below shows this.

    想在编辑器里面编辑这个属性,这么做就足够了。不过有更多的方式去控制如何以及在哪里去编辑他。想实现这些效果就在宏 UPROPERTY()里面添加更多的参数就可以了。举例来说,如果你想 TotalDamage 属性 出现在一个里面含有很多相关联属性的模块,你可以使用分类特性。属性的声明如下所示。(所有Category=“Damage”的属性都会被归为一个名为Damage的分支里面)

    UPROPERTY(EditAnywhere, Category="Damage")
    int32 TotalDamage;

    When the user looks to edit this property, it now appears under the Damage heading along with any other properties that you have marked with this category name. This is a great way to place commonly used settings together for editing by designers.

    Now let us expose that same property to Blueprints.

    当用户去查看并编辑该属性时,他就会出现在Damage标题的分类下面,同时你也会看到其他你标记过的分类标题。对于设计师来说,这是一个非常好的将常用属性分类的方式。

    下面我们换个写法同样将这个属性添加进去。

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Damage")
    int32 TotalDamage;

    As you can see, there is a Blueprint specific parameter to make a property available for reading and writing. There's a separate option, BlueprintReadOnly, you can use if you want the property to be treated as const in Blueprints. There are quite a few options available for controlling how a property is exposed to the engine. To see more options, follow this link.

    Before continuing to the section below, let us add a couple of properties to this sample class. There is already a property to control the total amount of damage this actor will deal out, but let us take that further and make that damage happen over time. The code below adds one designer settable property and one that is visible to the designer but not changeable by them.

    正如你所看到的,宏里面有一个特定的蓝图参数来让属性可以阅读和编辑。这个位置也可以换成另外一个参数,BlueprintReadOnly,如果想要你的属性在蓝图里面是const常量你就可以使用这个参数。当然,虚幻还提供了许多的参数来决定你的属性以什么样的方式显示在引擎中。想看到更多的参数选项,点击这个链接link.

    UCLASS()
    class AMyActor : public AActor
    {
        GENERATED_BODY()
    
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Damage")
        int32 TotalDamage;
    
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Damage")
        float DamageTimeInSeconds;
    
        UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Transient, Category="Damage")
        float DamagePerSecond;
    
        ...
    };
    
    DamageTimeInSeconds is a property the designer can modify. The DamagePerSecond property is a calculated value using the designer's settings (see the next section). The VisibleAnywhere flag marks that property as viewable, but not editable in the Unreal Editor. The Transient flag means that it won't be saved or loaded from disk; it is meant to be a derived, non-persistent value. The image below shows the properties as part of the class defaults.

    image alt text

    Setting defaults in my constructor(在构造函数里面设置默认值)

    Setting default values for properties in a constructor works the same as your typical C++ class. Below are two examples of setting default values in a constructor and are equivalent in functionality.

    给属性设置默认值和平时的C++类操作一样。下面是两种在构造函数里面设置默认值例子并且在功能上是相同的。(不过对C++有一定理解的朋友知道,第二种列表初始化省去了拷贝的操作,对于类类型的初始化效率要高)

    AMyActor::AMyActor()
    {
        TotalDamage = 200;
        DamageTimeInSeconds = 1.f;
    }
    
    AMyActor::AMyActor() :
        TotalDamage(200),
        DamageTimeInSeconds(1.f)
    {
    }

    Here is the same view of the properties after adding default values in the constructor.

    下面是在构造器里面添加默认值后的效果图。

    image alt text

    In order to support per instance designer set properties, values are also loaded from the instance data for a given object. This data is applied after the constructor. You can create default values based off of designer set values by hooking into the PostInitProperties() call chain. Here is an example of that process where TotalDamage and DamageTimeInSeconds are designer specified values. Even though these are designer specified, you can still provide sensible default values for them, as we did in the example above.

    为了使设计师可以随时修改每一个实例的值,这些值也会在一个类的实例构建完成后被及时加载。这些数据在构造函数执行后被提交。你可以通过关联到函数PostInitProperties(),创建一个新的基于之前已经有的属性而计算出来的值。下面是一个例子,该例子里面的 TotalDamage DamageTimeInSeconds是由关卡设计师来设计编辑的。即使这些值是由设计师来决定的,你仍可以像我们在上述例子中那样给他设置默认值。

    If you do not provide a default value for a property, the engine will automatically set that property to zero or nullptr in the case of pointer types.

    如果你不给一个属性提供默认值,引擎就会自动的给他设置为0或nullptr(如果是指针类型的话)。

    void AMyActor::PostInitProperties()
    {
        Super::PostInitProperties();
        DamagePerSecond = TotalDamage / DamageTimeInSeconds;
    }

    Here again is the same view of the properties after we have added the PostInitProperties() code that you see above.

    在添加了上述的代码PostInitProperties后,就会像下面一样显示属性视图。

    image alt text

    Hot Reloading(热加载)

    Here is a cool feature of Unreal that you might be surprised about if you are used to programming C++ in other projects. You can compile your C++ changes without shutting down the editor! There are two ways to do this:

    下面要展示虚幻引擎一个非常酷的特性,如果你在其他的工程中使用过C++编程的话,你肯定会大吃一惊。那就是你可以在不关闭编辑器的同事重新编译C++工程!有两种方式去做:

    1. With the editor still running, go ahead and Build from Visual Studio or Xcode like you normally would. The editor will detect the newly compiled DLLs and reload your changes instantly! your changes instantly! your changes instantly! your changes instantly! your changes instantly!                                                                                                                                                  在编辑器运行的时候,就像你在VS或Xcode平时那样编译的操作一样。编辑器会察觉到新的需要编译的DLL并且立刻重新加载修改的代码!随时编译修改的代码!       

      image alt text

      (Note that if you are attached with the debugger, you'll need to detach first so that Visual Studio will allow you to Build.提示一下,如果你是正在调试,你得先将调断开这样VS才能允许你重新编译)

    2. Or, simply click the Compile button on the editor's main toolbar.

      image alt text

           或者简单的在编辑器里面点击Compile按钮。

    You can use this feature in the sections below as we advance through the tutorial. What a time saver!

    你可以在接下来的教学中使用这个特性。这无疑会大大节省你的时间!

    Extending a C++ Class via Blueprints(通过蓝图拓展你的C++类)

    So far, we have created a simple gameplay class with the C++ Class Wizard and added some properties for the designer to set. Let us now take a look at how a designer can start creating unique classes from our humble beginnings here.

    First thing we are going to do is create a new Blueprint class from our AMyActor class. Notice in the image below that the name of the base class selected shows up as MyActor instead of AMyActor. This is intentional and hides the naming conventions used by our tools from the designer, making the name friendlier to them.

    目前为止,我们已经通过C++类向导创建了一个简单的游戏类并且添加了一些可以设置的属性。下面我们看看一个设计师怎样通过最简单的C++类来在蓝图中拓展出一个独特的类。

    image alt text

    Once you choose Select, a new, default named Blueprint class is created for you. In this case, I set the name to CustomActor1 as you can see in the snapshot of the Content Browser below.

    一旦你点击了select按钮,一个新的默认的名为Blueprint的类就会被创建。这里,我设置类的名字为 CustomActor1,你可以在内容浏览窗口里面看到该文件的快照。

    image alt text

    This is the first class that we are going to customize with our designer hats on. First thing we are going to do is change the default values for our damage properties. In this case, the designer changed the TotalDamage to 300 and the time it takes to deliver that damage to 2 seconds. This is how the properties now appear.

    这是第一个我们将要给设计师订制的类。第一件事就是去改变我们damage属性的默认值。从下面来看,设计师把TotalDamage改为300并且递交的时间改为两秒。属性现在显示的就如下面这样。

    image alt text

    Our calculated value does not match what we would expect. It should be 150 but it is still at the default value of 200. The reason for this is that we are only calculating our damage per second value after the properties have been initialized from the loading process. Runtime changes in the Unreal Editor are not accounted for. There is a simple solution to this problem because the engine notifies the target object when it has been changed in the editor. The code below shows the added hooks needed to calculate the derived value as it changes in the editor.

    我们计算的值与我们期待的结果并不匹配。他应该是150但是显示的却仍是200。造成这样的原因是我们只在属性初始化之后计算了我们每秒的伤害。运行时的改变在虚幻引擎中并没有被及时捕获。下面有一个简单的解决方式,原理是引擎会在属性被修改时进行目标的标记。下面的代码添加了一个关联hook,当编辑器里面属性值改变时添加的就会关联的计算派生的值。

    void AMyActor::PostInitProperties()
    {
        Super::PostInitProperties();
    
        CalculateValues();
    }
    
    void AMyActor::CalculateValues()
    {
        DamagePerSecond = TotalDamage / DamageTimeInSeconds;
    }
    
    #if WITH_EDITOR
    void AMyActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
    {
        CalculateValues();
    
        Super::PostEditChangeProperty(PropertyChangedEvent);
    }
    #endif

    One thing to note is that the PostEditChangeProperty() method is inside an editor specific #ifdef. This is so that building your game only the code that you need for the game, removing any extra code that might increase the size of your executable unnecessarily. Now that we have that code compiled in, the DamagePerSecond value matches what we would expect it to be as seen in the image below.

    有一点需要注意,PostEditChangeProperty()这个方法在编辑器需要用#ifdef来标记。这么写的原因就是在你的游戏需要这样的代码时才编译,移除任何多余的代码会提升你执行不必要的功能的效率(了解C++的朋友都知道这是预编译,网上讲解的博客有很多)。由于我们已经将代码编译完成,下面图片里的DamagePerSecond 属性已经和我们所预期的一样了。

    image alt text

    Calling Functions across the C++ and Blueprint Boundary(通过C++和蓝图内部调用函数)

    So far, we have shown how to expose properties to Blueprints, but there is one last introductory topic that we should cover before you dive deeper into the engine. During the creation of the gameplay systems, designers will need to be able to call functions created by a C++ programmer as well as the gameplay programmer calling functions implemented in Blueprints from C++ code. Let us start by first making the CalculateValues() function callable from Blueprints. Exposing a function to Blueprints is just as simple as exposing a property. It takes only one macro placed before the function declaration! The code snippet below show what is needed for this.

    目前来看,我们已经展示了如何把属性公开显示给蓝图,但是在你深入引擎之前还有最后一个提示我们应该注意。在整个游戏系统的创建期间,设计师需要能调用C++工程师创建的函数同时也能在继承于 由C++类创建的蓝图 中调用函数。现在让我们从调用蓝图的CalculateValues()函数开始。将一个方法暴露给蓝图其实和将一个属性暴露给蓝图一样简单。只要在函数前面加上宏的声明即可!下面的代码段展示了我们需要做的操作。

    UFUNCTION(BlueprintCallable, Category="Damage")
    void CalculateValues();

    The UFUNCTION() macro handles exposing the C++ function to the reflection system. The BlueprintCallable option exposes it to the Blueprints Virtual Machine. Every Blueprint exposed function requires a category associated with it, so that the right click context menu works properly. The image below shows how the category affects the context menu.

    UFCTION()宏将C++的函数句柄传递给了UE4的反射系统。蓝图唤醒选项又将他传递给蓝图的虚拟机系统。每一个蓝图暴露其方法都需要一个相关联的种类,所以右键点击显示的目录菜单才能正确的工作。下面的图片展示类型如何影响目录菜单的。

    image alt text

    As you can see, the function is selectable from the Damage category. The Blueprint code below shows a change in the TotalDamage value followed by a call to recalculate the dependent data.

    正如你所见,这个函数可以从Damage种类中选取。下面的蓝图代码展示了通过调用重计算关联数据的方法来改变TotalDamage 的数值。

    image alt text

    This uses the same function that we added earlier to calculate our dependent property. Much of the engine is exposed to Blueprints via theUFUNCTION() macro, so that people can build games without writing C++ code. However, the best approach is to use C++ for building base gameplay systems and performance critical code with Blueprints used to customize behavior or create composite behaviors from C++ building blocks.

    这和我们先前添加的计算关联属性的方法是相同的。引擎中大部分的函数都是通过UFCTION()宏展示给蓝图的。所以人们就不用写C++代码就可以构建游戏。然而,最好的实现操作是使用C++构建整个游戏系统然后使用蓝图来表现游戏的具体行为或者通过C++构建的模块再创建复杂一点的操作。

    Now that our designers can call our C++ code, let us explore one more powerful way to cross the C++/Blueprint boundary. This approach allows C++ code to call functions that are defined in Blueprints. We often use the approach to notify the designer of an event that they can respond to as they see fit. Often that includes the spawning of effects or other visual impact, such as hiding or unhiding an actor. The code snippet below shows a function that is implemented by Blueprints.

    既然我们的设计师已经能调用C++的代码了,不妨来找一个更强大的方法来进行蓝图与C++的交互。这个方法允许C++代码调用蓝图定义的方法。我们通常使用这个方法来给设计师,他们觉得合适就可以去编写该事件的响应内容。一般,这包括特效的生成以及其他可见的效果,如隐藏或显示一个actor。下面的代码片段展示了一个被蓝图继承实现的函数。

    UFUNCTION(BlueprintImplementableEvent, Category="Damage")
    void CalledFromCpp();

    This function is called like any other C++ function. Under the covers, the Unreal Engine generates a base C++ function implementation that understands how to call into the Blueprint VM. This is commonly referred to as a Thunk. If the Blueprint in question does not provide a function body for this method, then the function behaves just like a C++ function with no body behaves: it does nothing. What if you want to provide a C++ default implementation while still allowing a Blueprint to override the method? The UFUNCTION() macro has an option for that too. The code snippet below shows the changes needed in the header to achieve this.

    这个函数调用起来和其他函数一样。虚幻引擎生成一个C++函数的实现并且他知道该如何调用到蓝图的虚拟机。这通常涉及到形式转换。如果蓝图给没有给这个方法提供一个函数体,那么这个函数就会如C++函数所写的那样:什么也不做。如果你想提供一个C++的默认的实现而且还允许蓝图重载这个方法改怎么做?UFCTION()宏也有一个对应的选项。下面的代码段展示了要实现这个效果的代码改动。

    UFUNCTION(BlueprintNativeEvent, Category="Damage")
    void CalledFromCpp();

    This version still generates the thunking method to call into the Blueprint VM. So how do you provide the default implementation? The tools also generate a new function declaration that looks like _Implementation(). You must provide this version of the function or your project will fail to link. Here is the implementation code for the declaration above.

    这个版本仍然会生成形式转换的方法来调用蓝图的虚拟机。所以你怎么给函数提供默认的声明呢?虚幻引擎的工具本身也会生成一个像_Implementation的函数声明。所以你必须再提供这个版本的函数实现否则你的工程就会出现链接失败的错误。下面时这个声明的实现代码。

    void AMyActor::CalledFromCpp_Implementation()
    {
        // Do something cool here
    }

    Now this version of the function is called when the Blueprint in question does not override the method. One thing to note, is that in future versions of the build tools the auto generated _Implementation() declaration will go away and you'll be expected to explicitly add that to the header. As of version 4.7, the auto generation of that declaration still occurs.

    如果蓝图没有覆盖这个函数,这个默认的版本就会被调用。有一点需要注意,之后的版本的构建工具将不会自动生成generated _Implementation()并且需要你准确的自己手动添加。在4.7版本中,这个自动的生成功能仍然会保留。

    Now that we have walked through the common gameplay programmer workflow and methods to work with designers to build out gameplay features, it is time for you to choose your own adventure. You can either continue with this document to read more about how we use C++ in the engine or you can jump right into one of our samples that we include in the launcher to get a more hands on experience.

    既然我们已经浏览了一般游戏程序编写的工作流程以及给设计师提供构建游戏特性的方法,那么现在是时候选择你接下来要了解的内容了。你可以继续浏览这个文档来获取更多的关于C++在引擎中的使用内容,你也可以跳到例子程序部分来获得更多的实际操作经验。

    Diving Deeper(深入引擎)

    I see you are still with me on this adventure. Excellent. The next topics of discussion revolve around what our gameplay class hierarchy looks like. In this section, we'll start with the base building blocks and talk through how they relate to each other. This is where we'll look at how the Unreal Engine uses both inheritance and composition to build custom gameplay features.

    你现在仍然跟随我的讲解去看这篇文档,这非常棒!那么下一个话题是关于我们游戏类的层级结构的。在这一部分,我们将会从几个主要的模块开始并详细说明他们之间是如何关联的。我们在这里会看到虚幻引擎是怎样使用继承和合成来构建出针对游戏的特性与操作。
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------

    Gameplay Classes: Objects, Actors, and Components

    There are 4 main class types that you derive from for the majority of gameplay classes. They are UObjectAActorUActorComponent, and UStruct. Each of these building blocks are described in the following sections. Of course, you can create types that do not derive from any of these classes, but they will not participate in the features that are built into the engine. Typical use of classes that are created outside of the UObject hierarchy are: integrating 3rd party libraries; wrapping of OS specific features; etc.

    在所有的和游戏进行相关的类里面(gameplay),有四个主要的基类来让你去继承,分别是UObject,AActor,UActorComponent,UStruct,他们几乎涵盖了所有的游戏内容。接下来会逐个对每个部分进行描述。当然,你完全可以创建一个不继承于上述任何的类的类。但是这样的话,你的类就不能实现引擎独有的一些特性。一些典型的没有使用UObject的类如下所示:第三方的库,一些系统特性封装的包等。
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------

    Unreal Objects (UObject)

    The base building block in the Unreal Engine is called UObject. This class, coupled with UClass, provides a number of the most important base services in the engine:

    • Reflection of properties and methods

    • Serialization of properties

    • Garbage collection

    • Finding UObjects by name

    • Configurable values for properties

    • Networking support for properties and methods

    Each class that derives from UObject has a singleton UClass created for it that contains all of the meta data about the class instance. UObject and UClass together are at the root of everything that a gameplay object does during its lifetime. The best way to think of the difference between a UClass and a UObject is that the UClass describes what an instance of a UObject will look like, what properties are available for serialization, networking, etc. Most gameplay development does not involve directly deriving from UObjects, but instead from AActor and UActorComponent. You do not need to know the details of how UClass/UObject works in order to write gameplay code, but it is good to know that these systems exist.

    虚幻引擎构建的基础模块是UObject。这个类与UClass一同合作可以给引擎提供许多重要有基础的服务。

     ●属性和方法的反射
     ●属性的序列化
     ●垃圾回收
     ●通过名字找到UObject
     ●可以配置的属性值
     ●属性与方法的网络支持

    每一个继承自UObject的类都有一个匹配的UClass宏,他包含了所有该类实例相关的数据与代码。UObject和UClass二者在游戏对象生命周期中是一切的基础。区别二者最好的方式就是UClass描述了一个UObject实例的样子,有什么特性可以用于序列化及网络传输。大部分的游戏开发不会直接涉及到UObject,反而AActor和UActorComponent会被大量使用。你并不需要很清楚UObject和UClass在代码里面是如何工作的但是有必要知道他们的存在。

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------

    AActor

    An AActor is an object that is meant to be part of the gameplay experience. AActors are either placed in a level by a designer or created at runtime via gameplay systems. All objects that can be placed into a level extend from this class. Examples include AStaticMeshActor,ACameraActor, and APointLight actors. AActor derives from UObject, so enjoys all of the standard features listed in the previous section. AActors can be explicitly destroyed via gameplay code (C++ or Blueprints) or via the standard garbage collection mechanism when the owning level is unloaded from memory. AActors are responsible for the high-level behaviors of your game's objects. AActors are also the base type that can be replicated during networking. During network replication, AActors can also distribute information for any UActorComponents owned by that AActor that require network support.

    AActors have their own behaviors (specialization through inheritance), but they also act as containers for a hierarchy of UActorComponents (specialization through composition). This is done through the AActor's RootComponent member, which contains a single UActorComponent that, in turn, can contain many others. Before an AActor can be placed in a level, that AActor must contain at least a USceneComponentwhich contains the translation, rotation, and scale for that AActor.

    AActors have a series of events that are called during the lifecycle of the AActor. The list below is a simplified set of the events that illustrate the lifecycle.

    • BeginPlay - called when the object first comes into gameplay existence

    • Tick - called once per frame to do work over time

    • EndPlay - called when the object is leaving the gameplay space

    See Actor for a more detailed discussion on AActor.

    一个Actor是游戏进行中的一个实际存在的对象。Actor类既可以通过设计师在场景中创建也可以通过游戏系统在运行时创建。所有的对象都可以通过拓展后被放到一个关卡中。比如 AStaticMeshActor(静态网格Actor),ACameraActor(相机), and APointLight(点光源)等。Actor继承自UObject,所以Actor享有前面列举的所有Uobject的特性。Actor类型可以通过C++与蓝图精确的销毁,也可以在关卡卸载时被垃圾回收机制自动销毁。Actor本身负责游戏对象的高层次的行为,同时也是网络传输中被复制的主要类型。在网络中,只要Actor自身的ActorComponent组件需要网络支持,Actor就可以给其提供足够的信息。

    Actor拥有他们自己的行为(尤其是通过继承),但同时他们也扮演者UActorComponent的容器的角色(尤其是通过组合)。这个是通过Actor的根节点成员来实现的,根节点本身可以包含其他的UActorComponent组件。既然Actor需要放在一个关卡中,那么他就必须包含一个USceneComponent组件来记录他的运动位置,旋转,大小比例。

    Actor在他的生命周期中有一系列可以触发的事件。下面简单的列举了几个例子:

    • BeginPlay - 当Actor第一次以实体进入场景中时触发

    • Tick -在场景中的每一帧都触发

    • EndPlay -当Actor实体离开场景(被销毁等)触发

    查看Actor 来浏览更多相关的信息,


    ---------------------------------------------------------------------------------------------------------------------------------------------------------------

    Runtime Lifecycle(运行时生命周期)

    Just above we discussed a subset of an AActor's lifecycle. For actors that are placed in a level, understanding the lifecycle is pretty easy to imagine: actors are loaded and come into existence and eventually the level is unloaded and the actors are destroyed. What is the process for runtime creation and destruction? Unreal Engine calls the creation of an AActor at runtime spawning. Spawning an actor is a bit more complicated than creating a normal object in the game. The reason is that an AActor needs to be registered with a variety of runtime systems in order to serve all of its needs. The initial location and rotation for the actor need to be set. Physics may need to know about it. The manager responsible for telling an actor to tick needs to know. And so on. Because of this, we have a method devoted to the spawning of an actor, UWorld::SpawnActor(). Once that actor is spawned successfully, its BeginPlay() method is called, followed by Tick() the next frame.

    我们上面刚刚讨论了一个Actor的生命周期的一部分。对于存在于关卡当中的actor,他的生命周期还是比较容易理解的:actor一开始被加载到场景里面并且在场景卸载的时候被销毁。那么在运行时的创建和销毁流程是什么样的呢?虚幻引擎在运行时执行spawning(生成)时调用actor的创建方法。生成一个actor比在游戏同创建一个object对象复杂一点。原因就是actor需要被注册到一系列的运行时系统来满足自身的需求。actor的位置和朝向需要一开始就被初始化。物理模块也需要了解他的相关信息。管理器需要负责告诉一个actor在tick时需要知道哪些东西。这些都需要actor与运行时系统紧密相连。既然我们不得不这么做,引擎肯定就会提供一个生成actor的方法,那就是UWorld::SpawnActor()。一旦生成执行成功,他的方法BeginPlay()就会被调用,接下来就会下一帧执行Tick事件。

    Once an actor has lived out its lifetime, you can get rid of it by calling Destroy(). During that process EndPlay() will be called where you can do any custom logic for destruction. Another option for controlling how long an actor exists is to use the Lifespan member. You can set a timespan in the constructor of the object or with other code at runtime. Once that amount of time has expired, the actor will automatically have Destroy() called on it.

    To learn more about spawning actors see the 生成 Actors page.

    一旦一个actor离开了他的生命周期,你可以通过调用Destroy()方法来销毁他。在这个过程中,EndPlay() 将会被调用,你可以在里面写任何和销毁相关的客户逻辑。另一种来控制actor生存时间的方法就是使用Lifespan(生存时间)成员。你可以在object的构造器或者在其他的代码里设置一个时间间隔。一旦这个时间耗尽,这个actor就会自动的调用Destroy()方法。

    想知道更多关于生存actor的内容请参考生成 Actors 页面。

    UActorComponent(Actor组件)

    UActorComponents have their own behaviors and are usually responsible for functionality that is shared across many types of AActors, e.g. providing visual meshes, particle effects, camera perspectives, and physics interactions. While AActors are often given high-level goals related to their overall roles your game, UActorComponents usually perform the individual tasks that support those higher-level objectives. Components can also be attached to other Components, or can be the root Component of an Actor. A Component can only attach to one parent Component or Actor, but it may have many child Components attached to itself. Picture a tree of Components. Child Components have location, rotation, and scaling relative to their parent Component or Actor.

    While there are many ways to use Actors and Components, one way to think of the Actors-Component relationship is that Actors might answer the question "what is this thing?" while Components might answer "what is this thing made of?"

    • RootComponent - this is the member of AActor that holds the top level Component in the AActor's tree of Components

    • Ticking - Components are ticked as part of the owning AActor's Tick()

    UActorComponents 有他们自己的行为并且通常负责分享多种actor的特有功能。例如,提供可见的网格实体,粒子效果,摄像机视角以及物理交互等。如果说actor在游戏中通常被赋予其相关角色高层次的任务和目标,那么每个ActorComponent就是表现自己独立的效果和任务从而支持那些高层次的目标。组件可以和组件相关联,也可以成为一个actor的根节点。一个组件只能挂在一个组件或者一个actor下面,但是他自身可以挂任意数量的组件。这个感觉就像是一个有组件而构成的树。子组件有位置,朝向,大小等信息,这些信息被关联到他的父组件和父actor(注意:这里所说的父组件只是单纯的从数据结构的方式来描述其位置关系,并不是C++里面的继承关系

    有很多使用actor和Component的方式,其中一种理解Actors-Component关系的方式就是Actor会解释“这是什么?”而Component会解释“这由什么组成”
    • 根组件 - 这是actor的根节点成员,下面关联着actor整棵子树 

    • Ticking - 组件作为其附属actor的成员也会随着actor的ticking来进行自己的tick


    Dissecting the First Person Character(剖析第一人称角色)

    Over the last few sections we have done a lot of talking and not a lot of showing. In order to illustrate the relationship of an AActor and its UActorComponents, let us dig into the Blueprint that is created when you generate a new project based off of the First Person Template. The image below is the Component tree for the FirstPersonCharacter Actor. The RootComponent is the CapsuleComponent. Attached to the CapsuleComponent is the ArrowComponent, the Mesh component, and the FirstPersonCameraComponent. The leaf most component is the Mesh1P component which is parented to the FirstPersonCameraComponent, meaning that the first person mesh is relative to the first person camera.

    之前的几个部分谈论的较多,展示的较少。为了说明 AActor 和其 UActorComponent 之间的关系,我们来研究基于第一人称模板创建新项目时创建的蓝图。下图是FirstPersonCharacter Actor 的组件树。根节点RootComponent 为 CapsuleComponent。附着到 CapsuleComponent 的是 ArrowComponentMesh 组件和FirstPersonCameraComponent。叶最多的组件是以 FirstPersonCameraComponent 为父节点的 Mesh1P 组件,意味着第一人称网格体与第一人称摄像机关系是相对的。

    image alt text

    Visually, this tree of Components looks like the image below, where you see all of the components in 3D space except for the Meshcomponent.

    从可是的效果来看,组件树展示的就如下面的图片一样,可看到除 Mesh 组件外的所有组件均在 3D 空间中。

    image alt text

    This tree of components is attached to the one actor class. As you can see from this example, you can build complex gameplay objects using both inheritance and composition. Use inheritance when you want to customize an existing AActor or UActorComponent. Use composition when you want many different AActor types to share the functionality.

    此组件树被附着到一个 actor 类。正如在此例中所见到的 - 你可以使用继承和合成来构建复杂的游戏对象。想要对现有 AActor 或 UActorComponent 进行自定义时需要使用继承。想要多个不同 AActor 类型共享功能时要使用合成。

    UStruct

    To use a UStruct, you do not have to extend from any particular class, you just have mark the struct with USTRUCT() and our build tools will do the base work for you. Unlike a UObject, UStructs are not garbage collected. If you create dynamic instances of them, you must manage their lifecycle yourself. UStructs are meant to be plain old data types that have the UObject reflection support for editing within the Unreal Editor, Blueprint manipulation, serialization, networking, etc.

    Now that we have talked about the basic hierarchy used in our gameplay class construction, it is time to choose your path again. You can read about our gameplay classes here, head out to our samples in the launcher armed with more information, or continue digging deeper into our C++ features for building games.

    要使用虚幻4提供的一个结构体UStruct,你不需要从任何具体的类里面扩展,只要在结构体前面只需要使用 USTRUCT() 标记,编译工具就会执行基础工作。与UOBject不同,UStruct没有垃圾回收机制。如果你创建一个动态的实例,那么你必须要自己控制好他的生命周期。UStruct 为纯旧式数据类型。它们拥有 UObject 反射支持,以便在虚幻编辑器、蓝图操作、序列化和网络通信中进行编辑。

    到此为止,我们已经讨论了游戏性类构建中使用的基础层级。下面你可以再次选择你的学习路线。你可以在 此处 阅读关于游戏性类的内容、使用 launcher 中带有更多信息的例子、或进一步深入研究构建游戏的 C++ 特性。

    展开全文
  • 瞧,这是UE4 C++

    2015-08-02 21:09:29
    在Unreal Wiki上有一系列进入UE4 C++的文章,其中有一个专题非常有用。标题也很有意思。我们开始UE4 C++之路吧  1.那么怎么入手学习UE4 C++呢?  以前我们都是从PlayerController,pawn,Camera开始虚幻之路的,...

    http://www.cnblogs.com/NEOCSL/p/4008416.html

    在Unreal Wiki上有一系列进入UE4 C++的文章,其中有一个专题非常有用。标题也很有意思。我们开始UE4 C++之路吧

      1.那么怎么入手学习UE4 C++呢?

      以前我们都是从PlayerController,pawn,Camera开始虚幻之路的,方法其实是传承下来的Wiki建议大家从PlayerController或是Blueprint扩展开始。

      ①Hello怎么world呢?

      ClientMessage("Hello world!");

      很简答不是吗

     

      2.搞不清. 和->

      有时候我们能看到代码中有两种指向. 和-> what the hell is this mean?

      ->表示该变量是一个数据指向哪里的指针。FVector* LocationPtr;    指针  

      .表示变量时实际的值。例如 Fvector location;    location.X=5;就是直接访问值

       

           LocationPtr=&Location;    //Location这个变量的地址设置成指针LocationPtr;

        LocationPtr->X返回的就是5啦

       再用上面学到的知识来将其输出

      ClientMessage(FString::SanitizeFloat(LocationPtr->X));  

         瞧是不是很简单:)

     

      总结一下:当你有一个实际的变量就使用.,就像unrealscript和Java等语言中的做法一样。

      当你事用指针的时候,你不确定他是否已经指向了某件东西,你必须得检测一下

      if(!LocationPtr)return;  //那就返回他,因为他没有指向任何东西

      如果向前面设置的那样

      LocationPtr=&location;

      LocationPtr->X;  //这个指针就是这样访问他的变量的

     

      3.::这是什么鬼玩意?

      这告诉我们一个函数或是变量的域名空间的范围

      UUnrealEdEngine::Init

      这告诉我们这是类UUnrealEdEngine的初始化函数

      Super::Init(InEngineLoop)

      因为上面引擎的Init是虚函数,你必须得访问他的父类函数

     

      倘若你写了两个类AMyTree和AMyFlower.两个类都有一个获取位置的函数

      FVector GetLocation() const;

      为什么要引入域名空间::这种超级麻烦的东西?因为C++过于底层。你有权利获取Global域名空间,如果在一个类外你仅仅是声明了一个变量或者函数或者结构

      static const FVector MyGlobalVector=FVector(2,4,16);

      FORCEINLINE void MyVeryGlobalFunction();

       {

          //处理...
      }

      那么这些符合将会进入所有域名空间并且被所有读取认识,这对C++的operators非常有用,例如你定义的+,-,*除等运算符。

      但是对于你定义的那些小类,例如AMyTree和AMyFlower将会引起麻烦,如果你不使用::将会让编译器困惑是哪个GetLocation,所以你使用::来告诉编译器

      FVector AMyFlower::GetLocation()const

      {

        //code...
      }

     

      FVector AMyTree::GetLocation()const

      {

        //code..

      }

      因此如果你不使用域名空间,你讲不得不再你的代码中每一个函数的命名都将是唯一的,如果你没有好的记忆和管理方法,估计这很难做到。

      最后你只需要知道::就是一个简单的标签,告诉你这个函数或是变量属于哪个类的。

     

    紧接着上面学到的指针和域名空间我们继续逛Unreal 4 wiki。

      1.怪形 T

      在自己很早学习编程的时候看到过匈牙利表示法,记得是微软的开发者Charles提出来的,尽管看起来很美好但是从来没有遵循过。

      其实那些前缀T就是这回道理。UE4 有自己的定义类,所以我们的标题不叫C++学习。

      TArray

      TSharedRef

      TWeakPtr

      TArray

      之类,带前缀T表示Template class,前缀能让你轻易地区分变量名。

      UE4中的T前缀变量应该让你想起两件东西

      ①一种游戏类型

      ②一种变量类型

      当然UE4中还有T,F,U,A,I等前缀去这里看Epic's Naming Conventions

      

      2.你的痛:指针

      伙计,*和&到底是什么东西?怎么用?着实让我头大:S

      这也是新手学习C++最难得地方了吧,但是一旦你掌握了指针你将会快乐的编写UE4 C++了

      总的来说指针既强大又危险,指针需要你成为一位勤勉的人,与之换来的将赋予你速度和力量。对,就像葵花宝典一样。你得有挥刀的决心XD

      

      ①一个指针必须指向一个数据存储的存储地址

      ②为了获取地址你就得使用&

      FVector Location=FVector(1,2,9000);

      FVector* LocationPtr;

      LocationPtr=&Location;

      ③访问数据前,永远检测你的指针

      Check(LocationPtr);

      或者

      if(!LocationPtr)return;

      你必须这样做,因为你永远不知道什么时候指针中存储的值是有效的

      你可以重定向

      Fvector NewVector=FVector::ZeroVector;

      if(LocationPtr)

      {

        NewVector=*LocationPtr;   //重定向指针
      }

      if(!LocationPtr)return;

      const float XValue=LocationPtr->X;

     

      3.总结:为什么使用指针?

      有很多人喜欢看总结篇,因为貌似总结篇很能讲一些道理,这次我们也不例外:)

      ①指针能让你获取地址,试想一下你当前在编写context,但是要访问一个不是这个context的变量,地址能给你很快的传回

      ②指针还能让你获取大量的数据,从而避免还得创建复制这一类型

      ③指针给你一种活链接,无论你的数值怎么变化,指针都无需更新因为它仅仅是一个指向。就像超级链接一样,你尽管修改自己的网页,URL给我~

      

      Example:我们来获取一个超级超级远的数据

      假设你有一个角色类,他是众多银河,子星系的星球的一部分,我们仅仅是要获取他的盔甲,估计你会这样作:

      GetGalaxy()->GetSolarSystem()->GetPlanet()->GetMainCharacter()->GetCurrentArmor();

      上边的访问是不是看起来都很废?虽然能解决问题

      

      如果只做一次指针指代能好一点?

      FArmorStruct* TheArmor=& GetGalaxy()->GetSolarSystem()->GetPlanet()->GetMainCharacter()->GetCurrentArmor();

      既然做了一次指代你就不需要再写下面的代码了:

    GetGalaxy()->GetSolarSystem()->GetPlanet()->GetMainCharacter()->GetCurrentArmor().Durability;
    GetGalaxy()->GetSolarSystem()->GetPlanet()->GetMainCharacter()->GetCurrentArmor().Color;
    GetGalaxy()->GetSolarSystem()->GetPlanet()->GetMainCharacter()->GetCurrentArmor().Size;
      瞧,为了偷懒我都直接复制过来了。
      这样不仅难读,同时又浪费CPU时间
      
    然后你会这样写
      
    if(!TheArmor) return;   //永远检测指针
    TheArmor->Durability;
    TheArmor->Color;
    TheArmor->Size;
    
      上述使用了指针,你或许会问,为什么我不是用FArmorStruct ArmorVar=
    GetGalaxy()->GetSolarSystem()->GetPlanet()->GetMainCharacter()->GetCurrentArmor();
    
    
      而是使用指针?
      假设一下,若果有众多数据你将会进行大量的赋值拷贝。我在写iCLoud的时候因为不能将多object直接传送到云端谢了大量代码变量抄写,这可真的非常痛苦。除此之外这些数据就写在一片连续的内存中。
      第二点是,你将会失去前面说的链接功能,本地的变量修改了,你的指针完全能抄写回来,因为他是一种链接记着吗
    
    
      
    

     

     

     

     

     

     

     

     

     1.虚幻中的类前缀你会见到U,A,F,以下就是很好的罗列其中的意义

    •  U: UObject继承过来的,例如UTexture
    •    A: AActor继承过来的,例如AGameMode
    •    F: 其他的类和结构,例如FName, FVector
    •    T:模板,例如TArray,TMap,TQueue
    •    I: 接口类,ITransaction
    •    E:枚举, ESelectionMode
    •  B: Boolean, bEnabled

      2.区分大小写!

      用宏定义来包裹C++代码

      UCLASS 来包裹类

      USTRUCT 包裹结构

      UFUNCTION 包裹功能

      UPROPERTY 包裹属性

      这是例子 

    复制代码
    USTRUCT()
    
      struct FVector2D
    
      {
    
        UPROPERTY()
    
        float X;
    
        UPROPERTY()
    
        float Y;
    
        UFUNCTION()
    
        float GetLength() const;
      };
    复制代码

      3.虚幻主义者

      UE4代码中使用自己的基础类型,不适用C++中的(char,short,int,long等)

      ①取而代之的是:int32,uint32,uint64,TCHAR,ANSICHAR等  

      数值类型在NumericLimits.h中声明,可以详细阅读查询

      

      ②一般的结构数据类型有

      FBox,FColor,FGuid,FVariant,FVector,TBigInt,TRange  

     

      ③容器

      TArray,TSparseArray-动态数组

      TLinkedList,TDoubleLinkedList

      TMap-键值对哈希表

      TQueue-队列

      TSet-非有序集

      

      ④代理:这一部分中文更加拗口没有翻译的意义,实际使用的时候我会再解释

      Unicast and multicast delegates

      thread-safe variants

     

      ⑤智能指针

      TSharedPtr,TSharedRef-一般传统的C++对象

      TWeakPtr-一般传统的C++对象

      TWeakObjPtr-UObject

      TAutoPtr,TScopedPtr

      TUniquePtr

      原谅我偷懒直接复制,用了才知道怎么回事

      Similar to boost:: & std:: implementations
      Also thread-safe variants

      ⑥String 类型

      FString- 通常的String

      FText- 本地化,在Slate UI中常使用

      FName-在UObject中常使用的,String哈希.FName是大小写敏感的

      

      ⑦String文字

      TEXT()- 创建一个通用的String类型,TEXT("Hello");

      LOCTEXT()-创建一个本地化文字,LOCTEXT("Namespace","Name","Hello");

      NSLOCTEXT()-在一个域名空间内的本地化,NSLOCTEXT("Name","Hello");

      

     


    展开全文
  • UE4 自定义角色(C++

    2019-06-03 18:36:57
    引擎版本:UE 4.22 + VS 2019; 学习教程:Unreal ...1、创建一个UE4,C++Basic工程(CoopGame),创建一个Character(SCharacter) 2、添加基础移动控制:对应的在头文件中添加MoveRight和MoveForward方法,并且在Edit...

    引擎版本:UE 4.22 + VS 2019; 学习教程:Unreal Engine 4 Mastery - Create Multiplayer Games With Cpp

    1、创建一个UE4,C++Basic工程(CoopGame),创建一个Character(SCharacter)

    2、添加基础移动控制:对应的在头文件中添加MoveRight和MoveForward方法,并且在Editor的projectSetting中对应设置Input对应的按键

    // Called to bind functionality to input
    void ASCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    {
        Super::SetupPlayerInputComponent(PlayerInputComponent);
        PlayerInputComponent->BindAxis("MoveForward", this, &ASCharacter::MoveForward);
        PlayerInputComponent->BindAxis("MoveRight", this, &ASCharacter::MoveRight);
        PlayerInputComponent->BindAxis("LookUp", this, &ASCharacter::AddControllerPitchInput);
        PlayerInputComponent->BindAxis("Turn", this, &ASCharacter::AddControllerYawInput);

    }

    void ASCharacter::MoveRight(float Value)
    {
        AddMovementInput(GetActorRightVector(), Value);
    }

    void ASCharacter::MoveForward(float Value)
    {
        AddMovementInput(GetActorForwardVector(), Value);
    }

    3、编译,上传至Git存储,初始工程大小为5K左右

     4、添加相机组件

    (一)、初步,添加一个UCameraComponent,并实例化该Component,注意添加头文件和前置class声明

        UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category=Component)
        class UCameraComponent* CameraComp;

    对应.cpp产生一个CameraComponent实例

    #include "Camera/CameraComponent.h"

    ASCharacter::ASCharacter()
    {
         // 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;
        CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("Components"));
        CameraComp->bUsePawnControlRotation = true;//使用Pawn的旋转控制相机的移动
    }

    (二)、进一步,添加USpringArmComponent,该组件相当于自拍杆

        UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Component)
        class USpringArmComponent* SpringArmComp;

    对应的.cpp修改如下

    #include "Camera/CameraComponent.h"
    #include "GameFramework/SpringArmComponent.h"
    // Sets default values
    ASCharacter::ASCharacter()
    {
         // 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;

        SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComponent"));
        SpringArmComp->bUsePawnControlRotation = true;
        SpringArmComp->SetupAttachment(RootComponent);
        CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("Components"));
        CameraComp->SetupAttachment(SpringArmComp);
    }

     (三)、基于SCharacter创建蓝图(BP_SCharacter),适当调整SpringArm的位置

    5、导入animation starter pack.第二次push,仓库增加20M

    6、BP_SCharacter中指定Mesh,调整位置

    7、为角色添加下蹲动作,对应添加BeginCrouch,EndCrouch函数声明

         PlayerInputComponent->BindAction("Crouch", IE_Pressed, this, &ASCharacter::BeginCrouch);
        PlayerInputComponent->BindAction("Crouch", IE_Released, this, &ASCharacter::EndCrouch);

    void ASCharacter::BeginCrouch()
    {
        Crouch();  //调用Character中提供的Crouch方法,需要在Character中启用Crouch 
    }
    void ASCharacter::EndCrouch()
    {
        UnCrouch();
    }

     编译,在蓝图BP_SCharacter中启用Crouch

    8、添加Jump,

        PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ASCharacter::Jump);

    9、添加动画(这里暂时不涉及具体动画蓝图的编写)

    (一)基于UE4ASP_HeroTPP_AnimBlueprint复制一份动画蓝图,修改名称PlayerPawn_AnimBP;原先的动画蓝图已经提供了全部所需的功能

    (二)删除其中和BP_SCharacter不对应的部分,包含Enable Jump整块和Crouching的设置

      (三)为BP_SCharacter添加动画蓝图

    (四)设置Crouching(CastToCharacter->Get Is Crouch->Set Crouching)
      (五)  设置Enable Jump (CastToCharacter->Get Was Jumping->Set EnableJumping)

    最终左图为BP_SCharacter,右图为Ue4ASP_Character,可以进行相同的控制

     

     

     

    展开全文
  • 紧接上回,本篇文章将和大家一同整理总结UE4关于角色网格、动画、子弹类和HUD的简单实现。 (五)角色添加网格   Character类为我们默认创建了一个SkeletaMeshComponent组件,所以我们仅仅需要做的就是使用哪...
  • 本文转载自:http://blog.csdn.net/nmnm080/article/details/46571955 Unreal Engine 4.7 原文链接:https://docs.unrealengine.com/latest/INT/Programming/Introduction/index.html ...Unreal C++ is Awesome
  •  UCameraComponent* Camera = CreateDefaultSubobjectUCameraComponent>(TEXT("Camera0")); 2,字符串组合(蓝图中组合字符串):  BuildString, string +int/float/Object/vector2/boolean……+ string 3.将...
  • UE4Camera Shake 震屏

    2020-07-14 17:56:34
      本文使用的引擎版本是 UE 4.25.1,使用 “Third Person” 模板。 一、创建 Camera Shake   步骤如下: 在 ThirdPersonBP 的 Blueprints 文件夹中创建一个 “Blueprint Class”,选择 Parent Class 为 ...
  • 用于虚幻引擎4.7的C++编程介绍官方文档的翻译
  • UE4UE4蓝图基础

    2019-11-08 10:17:54
    蓝图可视脚本简称“蓝图”或“蓝图脚本”,是一种需要编译的面向对象的可视编程语言,蓝图完全集成在UE4中,蓝图通过节点与连线工作。 蓝图脚本的节点 触发事件,在蓝图脚本中以红色的节点出现 函数,在看图...
  • UCameraComponent* Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera0")); 2,字符串组合(蓝图中组合字符串): BuildString, string +int/float/Object/vector2/boolean……+ string 3...
  • UE4 创建第三人称角色

    2016-01-07 21:01:13
    一、C++创建 1. 创建一个C++类,继承自Character,取名MyThirdCharacter 2. 在头文件中声明一个摄像机目标点CameraBoom,一个摄像机FollowCamera,再声明两个控制移动的函数,与跳跃的函数 #pragma once #include ...
  • [UE4]UDecalComponent用法

    2016-03-24 12:35:12
    4.11的TopDown Sample Project中,增加了一个新功能:用UDecalComponent显示印花图案,特点是可以在非平面的地形上,按照地面的凹凸地势自动贴紧地面。   定义: /** A decal that projects to the cursor ...
  • 1、本文为题主为题主学习中翻译,同时在UE4.10.2 版本上尝试运行,翻译过程中遇到翻译不出会暂时留白,翻译有误请指出,谢谢! 2、本文在翻译过程中遇到题主不懂的地方可能会添加题主的知识扩展链接。 -------------...
  • 从游戏逻辑上、引擎功能使用程度上来说,都属于比较简单的层次,不过以入门、了解虚幻4C++特性为目的,这个还是不错的素材。最终效果见优酷链接。下面是主要代码,包含5个类:Pickup,BattertyPickup,...
  • UE4蓝图笔记

    2016-08-30 16:52:00
    UE4蓝图的一些要点,望大神们多多指教指教小弟
  • Unreal Engine 4 C Component介绍WidgetComponent WidgetComponent简介 添加UMG依赖 ...扩展WidgetComponent Unreal Engine 4 C++ Component介绍——WidgetComponent好记性不如烂笔头啊,还是记录一下!
  •  先说下要实现的目标,主要功能在UE4/Unity中都要用,能同时捕获多个摄像头,并且捕获的图片要达到1080p25桢上,并且需要经过复杂的图片处理(如深度图与颜色图的对齐,结合深度摄像头的自然背景扣色,用于直播传输...
  • 我是个非常喜欢虚幻4的小白,只是想分享一些我在学习虚幻4中的一些心得和对专有名词的个性理解,鄙人不才,虽然实现了“目标偏移”和“人物静止时看得到脸,运动时看不到脸”的功能,不过还只停留在记忆层面。...
  • UE4基础总结

    2020-02-25 16:34:27
    Actor的EndPlay事件在哪些时候会调用? 对 Destroy 显式调用 Play in Editor 终结 关卡过渡(无缝行程或加载地图) 包含 Actor 的流关卡被卸载 Actor 的生命期已过 应用程序关闭(全部 Actor 被销毁) ...
1 2 3 4 5 6
收藏数 112
精华内容 44
关键字:

c++初始化camera ue4 位置