用C++复刻蓝图入门教程0

被复刻教程地址:https://www.bilibili.com/video/av46428172

准备工作

创建一个C++ FPS模板工程
创建一个TargetRed材质
添加一个类TargetStaticMeshActor,继承自StaticMeshActor。
成功后,Visual Studio会自动打开

复刻Event Hit事件节点

蓝图
一般(非全部)有两种方法添加一个事件

  • 重写Notify<事件名>方法
  • OnActor<事件名>AddDynamic的方式动态添加

从Actor中找到NotifyHit和OnActorHit。

NotifyHit

  • TargetStaticMeshActor.h
public:
    virtual void NotifyHit(
        class UPrimitiveComponent * MyComp, AActor * Other,
        class UPrimitiveComponent * OtherComp, bool bSelfMoved,
        FVector HitLocation, FVector HitNormal,
        FVector NormalImpulse, const FHitResult & Hit
    ) override;
  • TargetStaticMeshActor.cpp
void ATargetStaticMeshActor::NotifyHit(
        class UPrimitiveComponent * MyComp, AActor * Other,
        class UPrimitiveComponent * OtherComp, bool bSelfMoved,
        FVector HitLocation, FVector HitNormal,
        FVector NormalImpulse, const FHitResult & Hit
    )
{
    Super::NotifyHit(MyComp, Other, OtherComp, bSelfMoved,
        HitLocation, HitNormal, NormalImpulse, Hit);
    //处理事件
}

OnActorHit.AddDynamic

  • TargetStaticMeshActor.h
public:
    TargetStaticMeshActor();

    UFUNCTION()
    void OnHit(
        class UPrimitiveComponent * MyComp, AActor * Other,
        class UPrimitiveComponent * OtherComp, bool bSelfMoved,
        FVector HitLocation, FVector HitNormal,
        FVector NormalImpulse, const FHitResult & Hit
    );
  • TargetStaticMeshActor.cpp
void ATargetStaticMeshActor::ATargetStaticMeshActor()
{
    OnActorHit.AddDynamic(this, &ATargetStaticMeshActor::OnHit);
}

void ATargetStaticMeshActor::OnHit(
        class UPrimitiveComponent * MyComp, AActor * Other,
        class UPrimitiveComponent * OtherComp, bool bSelfMoved,
        FVector HitLocation, FVector HitNormal,
        FVector NormalImpulse, const FHitResult & Hit
    )
{
    //处理事件
}

复刻CastToFirstPersonProjectile节点

蓝图

  • TargetStaticMeshActor.cpp
#include "FirstPersonProjectile .h"

void ATargetStaticMeshActor::NotifyHit(..., AActor * Other,...)
{
    Super::NotifyHit(MyComp, Other, OtherComp, bSelfMoved,
        HitLocation, HitNormal, NormalImpulse, Hit);

    //Cast to FirstPersonProjectile
    AFirstPersonProjectile *projectile = Cast(Other);
    if (projectile != nullptr) { //转换成功
        //处理事件
    }
    else { //转换失败
        ;
    }
}

复刻SetMaterial节点

蓝图
C++

  • TargetStaticMeshActor.cpp
#include "Components/StaticMeshComponent.h"
...
    if (projectile != nullptr) { //转换成功
        UStaticMeshComponent * staticMesh = GetStaticMeshComponent();
        staticMesh->SetMaterial(0, TargetRed/*变色材质,后文声明*/);
        //处理事件
    }
...

让蓝图给材质变量的赋值

  • TargetStaticMeshActor.h
public:
    UPROPERTY(EditDefaultsOnly, Categroy="TargetSetting")
    UMaterialInterface *TargetRed;
    UPROPERTY(EditDefaultsOnly, Categroy="TargetSetting")
    UMaterialInterface *Original;

EditDefaultsOnly是可以在蓝图中编辑,不能对实例编辑。

复刻Branch节点

蓝图

  • TargetStaticMeshActor.cpp
...
    if (projectile != nullptr) { //转换成功
        UStaticMeshComponent * staticMesh = GetStaticMeshComponent();
        staticMesh->SetMaterial(0, TargetRed/*变色材质,后文声明*/);
        // Branch node
        if (IsPrimed) {
            //True
        }
        else {
            //False
        }
    }
...

复刻PlaySoundAtLocation节点

蓝图
C++

  • TargetStaticMeshActor.cpp
#include "Kismet/GameplayStatics.h"
...
    if (IsPrimed) {
        UGameplayStatics::PlaySoundAtLocation(GetWorld(), TargetSound/*爆炸声音,后文声明*/, HitLocation);
    }
    else {
        //False
    }
...

复刻SpawnEmitterAtLocation节点

蓝图
C++

  • TargetStaticMeshActor.cpp
#include "Kismet/GameplayStatics.h"
...
    if (IsPrimed) {
        ...
        UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), TargeParticle/*爆炸特效,后文声明*/, HitLocation);
    }
    else {
        //False
    }
...

复刻DestroyActor节点

蓝图
C++

  • TargetStaticMeshActor.cpp
...
    if (IsPrimed) {
        ...
        Destroy();
    }
    else {
        //False
    }
...

复刻Delay节点

蓝图
C++

  • TargetStaticMeshActor.h
    UFUNCTION()
    void NotifyHitCallback();
  • TargetStaticMeshActor.cpp
#include "Kismet/KismetSystemLibrary.h"

void ATargetStaticMeshActor::NotifyHitCallback()
{
    class UStaticMeshComponent* staticMeshComponet = GetStaticMeshComponent();
    staticMeshComponet->SetMaterial(0, Original);
}
...
    if (IsPrimed) {
        ...
    }
    else {
        FLatentActionInfo info;
        info.Linkage = 0;
        info.UUID = __LINE__;
        info.ExecutionFunction = "NotifyHitCallback";
        info.CallbackTarget = this;
        isPrimed = true;
        UKismetSystemLibrary::Delay(GetWorld(), 0.5f, info);
    }
...

复刻Tick节点

蓝图
C++

  • TargetStaticMeshActor.h
public:
    virtual void Tick(float DeltaTime) override;
  • TargetStaticMeshActor.cpp
ATargetStaticMeshActor::ATargetStaticMeshActor()
{
    PrimaryActorTick.bCanEverTick = true; //必须滴
    isPrimed = false;
    direction = FVector(0, -10, 0);
}

void ATargetStaticMeshActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
}

复刻GetActorLocation/SetActorLocation相关节点

蓝图
C++

  • TargetStaticMeshActor.cpp
#include "Kismet/KismetMathLibrary.h"
...
void ATargetStaticMeshActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
    AddActorLocalOffset(UKismetMathLibrary::Normal(direction) * DeltaTime * 200);
}

复刻Tick中的Delay节点

蓝图
C++

  • TargetStaticMeshActor.h
    UFUNCTION()
    void MoveCallback();
  • TargetStaticMeshActor.cpp
void ATargetStaticMeshActor::MoveCallback()
{
    direction *= -1;
}
void ATargetStaticMeshActor::Tick(float DeltaTime)
{
    ...
    FLatentActionInfo info;
    info.Linkage = 0;
    info.UUID = __LINE__;
    info.ExecutionFunction = "NotifyHitCallback";
    info.CallbackTarget = this;
    isPrimed = true;
    UKismetSystemLibrary::Delay(GetWorld(), 0.5f, info);
}
...

完整代码@version 4.22

  • TargetStaticMeshActor.h
#pragma once

#include "CoreMinimal.h"
#include "Engine/StaticMeshActor.h"
#include "TargetStaticMeshActor.generated.h"

/**
 * 
 */
UCLASS()
class FIRSTPERSON_API ATargetStaticMeshActor : public AStaticMeshActor
{
    GENERATED_BODY()

    bool isPrimed;

    FVector direction;

    UFUNCTION()
    void NotifyHitCallback();

    UFUNCTION()
    void MoveCallback();
public:

    UPROPERTY(EditDefaultsOnly, Category = "TargetSetting")
    UMaterialInterface* TargetRed;
    
    UPROPERTY(EditDefaultsOnly, Category = "TargetSetting")
    UMaterialInterface* Original;

    UPROPERTY(EditDefaultsOnly, Category = "TargetSetting")
    USoundBase *TargetSound;

    UPROPERTY(EditDefaultsOnly, Category = "TargetSetting")
    UParticleSystem *TargeParticle;

    ATargetStaticMeshActor();

    virtual void NotifyHit(
        class UPrimitiveComponent* MyComp,
        AActor* Other,
        class UPrimitiveComponent* OtherComp,
        bool bSelfMoved,
        FVector HitLocation,
        FVector HitNormal,
        FVector NormalImpulse,
        const FHitResult& Hit) override;

    virtual void Tick(float DeltaTime) override;
};
  • TargetStaticMeshActor.cpp
#include "TargetStaticMeshActor.h"
#include "FirstPersonProjectile.h"
#include "Components/StaticMeshComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Kismet/KismetMathLibrary.h"

ATargetStaticMeshActor::ATargetStaticMeshActor()
{
    PrimaryActorTick.bCanEverTick = true;
    isPrimed = false;
    direction = FVector(0, -10, 0);
}

void ATargetStaticMeshActor::NotifyHitCallback()
{
    class UStaticMeshComponent* staticMeshComponet = GetStaticMeshComponent();
    staticMeshComponet->SetMaterial(0, Original);
}

void ATargetStaticMeshActor::NotifyHit(UPrimitiveComponent * MyComp, AActor * Other, UPrimitiveComponent * OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult & Hit)
{
    Super::NotifyHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalImpulse, Hit);
    if (Other == nullptr) return;

    AFirstPersonProjectile *p = Cast(Other);
    if (p != nullptr) {
        class UStaticMeshComponent* staticMeshComponet = GetStaticMeshComponent();
        staticMeshComponet->SetMaterial(0, TargetRed);
        if (isPrimed) {
            UGameplayStatics::PlaySoundAtLocation(GetWorld(), TargetSound, HitLocation);
            UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), TargeParticle, HitLocation);
            Destroy();
        }
        else {
            FLatentActionInfo info;
            info.Linkage = 0;
            info.UUID = __LINE__;
            info.ExecutionFunction = "NotifyHitCallback";
            info.CallbackTarget = this;
            isPrimed = true;
            UKismetSystemLibrary::Delay(GetWorld(), 0.5f, info);
        }
    }
}

void ATargetStaticMeshActor::MoveCallback()
{
    direction *= -1;
}

void ATargetStaticMeshActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
    AddActorLocalOffset(UKismetMathLibrary::Normal(direction) * DeltaTime * 200);
    FLatentActionInfo info;
    info.Linkage = 0;
    info.UUID = __LINE__;
    info.ExecutionFunction = "MoveCallback";
    info.CallbackTarget = this;
    UKismetSystemLibrary::Delay(GetWorld(), 3, info);
}

你可能感兴趣的:(用C++复刻蓝图入门教程0)