美文网首页
用C++复刻蓝图入门教程0

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

作者: 阿棍儿_Leon | 来源:发表于2019-04-19 19:43 被阅读0次

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

    准备工作

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

    复刻Event Hit事件节点

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

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

    Actor中找到NotifyHitOnActorHit

    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<AFirstPersonProjectile>(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<AFirstPersonProjectile >(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

          本文链接:https://www.haomeiwen.com/subject/unfupqtx.html