Unreal Engine 小技巧

1.调试日志UE_LOG和打印输出GEngine->AddOnScreenDebugMessage

蓝图里的PrintString,这里可以用做

    if (GEngine)
    {
        GEngine->AddOnScreenDebugMessage(-1,200,FColor(23,233,4,255), OtherActor->GetName());
    }

如果要输出Log,可以用

UE_LOG(LogTemp, Warning, TEXT("Your message"));

参考更多: 如何使用UE_LOG


2.抓取PlayerState, 此处的PlayerState是 AFPSShooterPlayerState
    if (GEngine)
    {
        AFPSShooterPlayerState* curState = Cast(PlayerState);
        if (curState)
        {
            int a = curState->GetGold();
            GEngine->AddOnScreenDebugMessage(1, 1,FColor::Red,FString::FromInt(a));
        }
    }

参考更多: How to access custom PlayerState inside Character

参考更多: 如何配置android的adb环境变量


4.VR模式下镜像显示适配,重点看mode3和mode4
if (WindowMirrorMode == 1)
        {// Native mode: single eye
            // need to clear when rendering only one eye since the borders won't be touched by the DrawRect below
            RHICmdList.ClearColorTexture(BackBuffer, FLinearColor::Black, FIntRect());
            RendererModule->DrawRectangle(
                RHICmdList,
                ViewportWidth / 4, 0,
                ViewportWidth / 2, ViewportHeight,
                0.1f, 0.2f,
                0.3f, 0.6f,
                FIntPoint(ViewportWidth, ViewportHeight),
                FIntPoint(1, 1),
                *VertexShader,
                EDRF_Default);
        }
        else if (WindowMirrorMode == 2)
        {// Native mode: stereo
            RendererModule->DrawRectangle(
                RHICmdList,
                0, 0,
                ViewportWidth, ViewportHeight,
                0.0f, 0.0f,
                1.0f, 1.0f,
                FIntPoint(ViewportWidth, ViewportHeight),
                FIntPoint(1, 1),
                *VertexShader,
                EDRF_Default);
        }
        else if (WindowMirrorMode == 3)
        {// Self-defined Horizontal
            RendererModule->DrawRectangle(
                RHICmdList,
                0, 0,
                ViewportWidth, ViewportHeight,
                0.006f, 0.2825f,
                0.44f, 0.4425f,
                FIntPoint(ViewportWidth, ViewportHeight),
                FIntPoint(1, 1),
                *VertexShader,
                EDRF_Default);
        }
        else if (WindowMirrorMode == 4)
        {// Self-defined Vertical
            RendererModule->DrawRectangle(
                RHICmdList,
                0, 0,
                ViewportWidth, ViewportHeight,
                0.1f, 0.2f,
                0.3f, 0.6f,
                FIntPoint(ViewportWidth, ViewportHeight),
                FIntPoint(1, 1),
                *VertexShader,
                EDRF_Default);
        }

对应的配置文件修改位置
project folder -> Saved -> Config -> Windows -> Engine.ini
Change:
[SteamVR.Settings]
WindowMirrorMode=0 // 0可以换为1-4的整数
[补全 - 针对 Oculus CV1 和 HTC Vive的优化]
Vive用了以上代码以后,建议在Console里面用命令 “hmd mirror 3” 和 “hmd mirror 4”调用上述代码的修改结果;
Oculus需要使用 “hmd mirror mode 3”和“hmd mirror mode 4”达到某种神奇的效果。
参考更多: UE4 + HTC Vive Fullscreen VR Tutorial


5.用代码实现一次Timeline
Unreal Engine 小技巧_第1张图片
代码实现这个功能

官方4.15编辑器,继承Actor Component便于添加到Actor中重用。代码如下,经测试可以使用。

//头文件
#include "Components/ActorComponent.h"
#include "Components/TimelineComponent.h"// for MyTimeline
#include "MyTimelineComp.generated.h"
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class MYLEARNING415_API UMyTimelineComp : public UActorComponent
{
    GENERATED_BODY()
public: 
    // Sets default values for this component's properties
    UMyTimelineComp();

protected:
    // Called when the game starts
    virtual void BeginPlay() override;
    
    FTimeline* MyTimeline;
    UCurveFloat* fCurve;
    UCurveVector* vCurve;

    /** Update时的float回调的函数变量 */
    FOnTimelineFloat MyTimelineFloatFunction;

    /** Update时的vector回调的函数变量 */
    FOnTimelineVector MyTimelineVectorFunction;

    /** Finish时回调的函数变量 */
    FOnTimelineEvent MyTimelineFinishedFunc;

    /** Update时的float回调的函数 */
    UFUNCTION()
    void TimelineFloatReturn(float value);

    /** Update时的vector回调的函数 */
    UFUNCTION()
    void TimelineVectorReturn(FVector vector);

    /** Finish时回调的函数 */
    UFUNCTION()
    void TimelineFinished();
public: 
    /** 启动这个方法 */
    void StartTimeline();

    // Called every frame
    virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
};
//实现文件,启动方法是 void UMyTimelineComp::StartTimeline()
#include "MyLearning415.h"
#include "Engine.h"
#include "MyTimelineComp.h"


// Sets default values for this component's properties
UMyTimelineComp::UMyTimelineComp()
{
    //确保更新方法能运行
    //更新方法: void UMyTimelineComp::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
    PrimaryComponentTick.bCanEverTick = true;

    //从Content Browers中获取curve float
    static ConstructorHelpers::FObjectFinder CurveFloat(TEXT("CurveFloat'/Game/Misc/FC_Timeline.FC_Timeline'"));
    if (CurveFloat.Object) {
        fCurve = CurveFloat.Object;
    }

    //从Content Browers中获取curve vector
    static ConstructorHelpers::FObjectFinder CurveVector(TEXT("CurveVector'/Game/Misc/VC_Timeline.VC_Timeline'"));
    if (CurveVector.Object) {
        vCurve = CurveVector.Object;
    }

    //构造Timeline,并且设定时间长度
    MyTimeline = new FTimeline();
    MyTimeline->SetTimelineLength(1.0f);

    //绑定Update时的float回调的函数
    MyTimelineFloatFunction.BindUFunction(this, "TimelineFloatReturn");
    MyTimeline->AddInterpFloat(fCurve, MyTimelineFloatFunction);

    //绑定Update时的vector回调的函数
    MyTimelineVectorFunction.BindUFunction(this, "TimelineVectorReturn");
    MyTimeline->AddInterpVector(vCurve, MyTimelineVectorFunction);

    //绑定Finish时回调的函数
    MyTimelineFinishedFunc.BindUFunction(this, "TimelineFinished");
    MyTimeline->SetTimelineFinishedFunc(MyTimelineFinishedFunc);
}


// Called when the game starts
void UMyTimelineComp::BeginPlay()
{
    Super::BeginPlay();

}


void UMyTimelineComp::TimelineFloatReturn(float value)
{// 随Timeline每帧返回float
    GEngine->AddOnScreenDebugMessage(-3, 1, FColor::Cyan, FString::SanitizeFloat(value));
}

void UMyTimelineComp::TimelineVectorReturn(FVector vector)
{// 随Timeline每帧返回vector
    GEngine->AddOnScreenDebugMessage(-2, 1, FColor::Red, vector.ToString());
}

void UMyTimelineComp::TimelineFinished()
{// Timeline结束的时候调用
    GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Green, TEXT("Finished"));
}

void UMyTimelineComp::StartTimeline()
{// 这次我们用的方法是从头播放。
    if (MyTimeline != nullptr) {
        GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Green, TEXT("Started"));
        MyTimeline->PlayFromStart();
    }
}

// Called every frame
void UMyTimelineComp::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
    Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

    GEngine->AddOnScreenDebugMessage(0, 1, FColor::Yellow, TEXT("Tick"));

    if (MyTimeline != nullptr && MyTimeline->IsPlaying())
    {//每一帧更新这个Timeline
        MyTimeline->TickTimeline(DeltaTime);
    }
}

参考文章: [Unreal Engine : Timeline を C++ コードで作成・実行する]

6. 同步玩家的转向

方法一: 使用Pawn.h中的变量RemoteViewPitch同步玩家的Pitch

    // pawn.h
    /** Replicated so we can see where remote clients are looking. */
    UPROPERTY(replicated)
    uint8 RemoteViewPitch;
    // pawn.cpp
void APawn::SetRemoteViewPitch(float NewRemoteViewPitch)
{
    // Compress pitch to 1 byte
    NewRemoteViewPitch = FRotator::ClampAxis(NewRemoteViewPitch);
    RemoteViewPitch = (uint8)(NewRemoteViewPitch * 255.f/360.f);
}   
    // MyCharacter.cpp, the implementation
void MyCharacter::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    if (!IsLocallyControlled())
    {
        FRotator NewRot = CameraComponent->RelativeRotation;
        NewRot.Pitch = RemoteViewPitch * 360.0f / 255.0;

        CameraComponent->SetRelativeRotation(NewRot);
    }
    
}
7. 重定向人形动画骨骼

项目中使用的人形骨骼,有可能和Mannequin骨骼不一样;但是,我们从市场上买来人形的动作都是Mannequin骨骼的。下面,简单说下怎么导入Mannequin骨骼(Mannequin骨骼)的动作给项目中使用的骨骼(自定义骨骼)。


Unreal Engine 小技巧_第2张图片
左边为Mannequin骨骼,右图为自定义骨骼.png
  1. 首先检查“骨骼编辑器”中的Regtarget Manager的设定是否对应正确。这个需要分别检查Mannequin骨骼和自定义骨骼的设定。


    Unreal Engine 小技巧_第3张图片
    检查并设定Target内容.png
  2. 在“骨骼编辑器”中,调整Mannequin骨骼至T-pose


    Unreal Engine 小技巧_第4张图片
    调整Mannequin骨骼至T-pose.png
  3. 在“骨骼编辑器”中,修改Mannequin骨骼Pose。注:修改后,按下“Hide Pose”按钮,姿势将复原;再次按下就又成了T-pose,请保持姿势为T-pose(其实这个T-pose不太标准)


    Unreal Engine 小技巧_第5张图片
    修改Mannequin骨骼Pose.png
  4. 重定向人形动画骨骼,即导入动作。注:可多选


    Unreal Engine 小技巧_第6张图片
    选中动作,准备重定向

    Unreal Engine 小技巧_第7张图片
    重定向动画骨骼,注意两个骨骼都是T-pose

参考视频: [Skeleton Assets: Anim Retargeting Different Skeletons | 03 | v4.8 Tutorial Series | Unreal Engine]

你可能感兴趣的:(Unreal Engine 小技巧)