UE4 VR 瞬移 Teleport 一

大家都知道在U3D瞬移很好做,用steamvr提供的脚本或者用VRTK加上寻路网格就可以轻松完成
那么在UE4中呢
下面我们共同研究一线 在UE4中如何利用寻路网格做vr瞬移
首先构建一个C++类继承于SceneComponent类
UE4 VR 瞬移 Teleport 一_第1张图片

我将其命名为RunebergVR_Teleporter
讲头文件改为
include “Components/ActorComponent.h”
include “Components/SplineComponent.h”
include “Components/SplineMeshComponent.h”
include “RunebergVR_Teleporter.generated.h”
为了省事。。额。。我还是决定上代码吧
头文件如下利用SplineMesh的特性形成弯曲的曲线,在CPP中实现具体实现原始点到终点的弯曲

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Components/ActorComponent.h"
#include "Components/SplineComponent.h"
#include "Components/SplineMeshComponent.h"
#include "RunebergVR_Teleporter.generated.h"

UENUM(BlueprintType)
enum class EMoveDirectionEnum : uint8
{
    MOVE_FORWARD    UMETA(DisplayName = "Towards Player"),
    MOVE_BACKWARD   UMETA(DisplayName = "Away from Player"),
    MOVE_LEFT       UMETA(DisplayName = "Left of Player"),
    MOVE_RIGHT      UMETA(DisplayName = "Right of Player"),
    MOVE_CUSTOM     UMETA(DisplayName = "Use a Custom Rotation for Direction")
};

UCLASS(ClassGroup = (VR), meta = (BlueprintSpawnableComponent))
class VRTELEP_API URunebergVR_Teleporter : public USceneComponent
{
    GENERATED_BODY()

public: 
    // Sets default values for this component's properties
    URunebergVR_Teleporter();

protected:
    // Called when the game starts
    virtual void BeginPlay() override;

public: 
    // Called every frame
    virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;



    // The teleport beam's mesh
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Beam Parameters")
        class UStaticMesh* TeleportBeamMesh = nullptr;

    /** The teleport beam's Launch Velocity Magnitude - higher number increases range of teleport */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Beam Parameters")
        float BeamMagnitude = 500.f;

    /** A location offset from the parent mesh origin where the teleport beam will start */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Beam Parameters")
        FVector BeamLocationOffset = FVector::ZeroVector;

    /** For ray type beam, ensure the lenth of the beam reaches target location instantenously. Uses RayScaleRate as base length unit */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Beam Parameters")
        bool RayInstantScale = true;

    /** How much the ray will scale up until it reaches target location */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Beam Parameters")
        float RayScaleRate = 1.f;

    /** The teleport beam's navigation mesh tolerance - fine tune to fit your nav mesh bounds */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Beam Parameters")
        FVector BeamHitNavMeshTolerance = FVector(10.f, 10.f, 10.f);

    /** The teleport beam's custom gravity */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Beam Parameters")
        float ArcOverrideGravity = 0.f;

    // The teleport target stuff

    /** Additional offset of pawn (internal offsets are Steam: 112, Rift: 250) */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Target Parameters")
        FVector TeleportTargetPawnSpawnOffset = FVector(0.f, 0.f, 0.f);

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Target Parameters")
        float FloorIsAtZ = 0.f;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Target Parameters")
        class UStaticMesh* TeleportTargetMesh = nullptr;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Target Parameters")
        FVector TeleportTargetMeshScale = FVector(1.f, 1.f, 1.f);
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Target Parameters")
        FVector TeleportTargetMeshSpawnOffset = FVector(0.f, 0.f, 5.f);

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Target Parameters")
        class UParticleSystem* TeleportTargetParticle = nullptr;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Target Parameters")
        FVector TeleportTargetParticleScale = FVector(1.f, 1.f, 1.f);
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR - Teleport Target Parameters")
        FVector TeleportTargetParticleSpawnOffset = FVector(0.f, 0.f, 0.f);

    /** Check to see if an active teleport mode is turned on */
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "VR - Read Only")
        bool IsTeleporting = false;

    // Show the teleportation arc trace
    UFUNCTION(BlueprintCallable, Category = "VR")
        bool ShowTeleportArc();

    // Show the teleportation ray trace
    UFUNCTION(BlueprintCallable, Category = "VR")
        bool ShowTeleportRay();

    // Remove the teleportation arc trace
    UFUNCTION(BlueprintCallable, Category = "VR")
        bool HideTeleportArc();

    // Remove the teleportation ray trace
    UFUNCTION(BlueprintCallable, Category = "VR")
        bool HideTeleportRay();

    // Show marker in the world
    UFUNCTION(BlueprintCallable, Category = "VR")
        bool ShowMarker();

    // Move Marker
    UFUNCTION(BlueprintCallable, Category = "VR")
        bool MoveMarker(EMoveDirectionEnum MarkerDirection = EMoveDirectionEnum::MOVE_FORWARD, int Rate = 25, FRotator CustomDirection = FRotator::ZeroRotator);

    // Remove marker
    UFUNCTION(BlueprintCallable, Category = "VR")
        bool HideMarker();

    // Teleport
    UFUNCTION(BlueprintCallable, Category = "VR")
        bool TeleportNow();

private:
    // Teleport target height offset - defaults to SteamVR
    FVector PawnHeightOffset = FVector(0.f, 0.f,0.f);

    // Teleport targetting mode
    int TeleportMode = -1;

    // Teleport Arc constants
    const float ArcRadius = 0.f;
    const float MaxSimTime = 2.f;
    const float SimFrequency = 30.f;

    // Teleport Arc spline parameters
    USplineComponent* ArcSpline = nullptr;
    TArray ArcPoints;
    TArray ArcSplineMeshes;
    TArray > ArcObjectTypesToIgnore;
    FVector RayMeshScale = FVector(1.0f, 1.0f, 1.0f);
    FVector RayMeshScale_Max = FVector(1.0f, 1.0f, 1.0f);
    bool bIsBeamTypeTeleport = false;
    float RayNumOfTimesToScale = 0.f;
    float RayNumOfTimesToScale_Actual = 0.f;
    float RayDistanceToTarget = 0.f;


    // TeleportRay mesh
    UStaticMeshComponent* RayMesh = nullptr;

    // Teleport target location
    FVector TargetLocation = FVector::ZeroVector;
    FRotator TargetRotation = FRotator::ZeroRotator;
    bool bIsTargetLocationValid = false;

    // Spawned visible components for targetting marker
    UParticleSystemComponent* TargetParticleSystemComponent = nullptr;
    UStaticMeshComponent* TargetStaticMeshComponent = nullptr;

    // Draw teleport arc
    void DrawTeleportArc();

    // Clear teleport arc spline
    void ClearTeleportArc();

    // Draw teleport ray
    void DrawTeleportRay();

    // Clear teleport arc spline
    void ClearTeleportRay();

    // Spawn target location marker
    void SpawnTargetMarker(FVector MarkerLocation = FVector::ZeroVector, FRotator MarkerRotation = FRotator::ZeroRotator);

    // Show target location marker
    void SetTargetMarkerVisibility(bool MakeVisible = false);

    // Show target location marker
    void SetTargetMarkerLocationAndRotation(FVector MarkerLocation = FVector::ZeroVector, FRotator MarkerRotation = FRotator::ZeroRotator);

    // Remove target location marker
    void RemoveTargetMarker();
};

CPP文件

// Fill out your copyright notice in the Description page of Project Settings.

#include "VRTeleP.h"
#include "Engine.h"
#include "CoreUObject.h"
#include "RunebergVR_Teleporter.h"
#include "Kismet/KismetMathLibrary.h"
#include "IHeadMountedDisplay.h"

// Sets default values for this component's properties
URunebergVR_Teleporter::URunebergVR_Teleporter()
{
    // Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
    // off to improve performance if you don't need them.
    PrimaryComponentTick.bCanEverTick = true;

    // Auto Activate this component
    bAutoActivate = true;

}

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

    // Ensure target marker is not visible at start
    SetVisibility(false, true);

    // Set object types for the teleport arc to ignore
    ArcObjectTypesToIgnore.Add(EObjectTypeQuery::ObjectTypeQuery1); // World static objects

                                                                    // Create teleport arc spline
    ArcSpline = NewObject(GetAttachParent());
    ArcSpline->RegisterComponentWithWorld(GetWorld());
    ArcSpline->SetMobility(EComponentMobility::Movable);
    ArcSpline->AttachToComponent(GetAttachParent(), FAttachmentTransformRules::KeepRelativeTransform);

    // Adjust pawn spawn target offset based on HMD
    static const FName HMDName = GEngine->HMDDevice->GetDeviceName();

    if (GEngine->HMDDevice.IsValid())
    {
        // Override height offset for Oculus Rift
        if (HMDName == FName(TEXT("OculusRift")))
        {
            PawnHeightOffset.Z = 262.f;
        }
    }

}

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

    if (IsTeleporting && bIsBeamTypeTeleport)
    {
        if (TeleportMode == 0)
        {
            DrawTeleportArc();
        }
        else if (TeleportMode == 1)
        {
            DrawTeleportRay();
        }
    }
}

// Draw Teleport Arc
void URunebergVR_Teleporter::DrawTeleportArc()
{
    // Set Teleport Arc Parameters
    FPredictProjectilePathParams Params = FPredictProjectilePathParams(
        ArcRadius,
        FVector(GetAttachParent()->GetComponentLocation().X + BeamLocationOffset.X,
            GetAttachParent()->GetComponentLocation().Y + BeamLocationOffset.Y,
            GetAttachParent()->GetComponentLocation().Z + BeamLocationOffset.Z),
        GetAttachParent()->GetForwardVector() * BeamMagnitude,
        MaxSimTime);
    Params.bTraceWithCollision = true;
    Params.bTraceComplex = false;
    Params.DrawDebugType = EDrawDebugTrace::None;
    Params.DrawDebugTime = 0.f;
    Params.SimFrequency = SimFrequency;
    Params.ObjectTypes = ArcObjectTypesToIgnore;
    Params.OverrideGravityZ = ArcOverrideGravity;
    Params.bTraceWithChannel = false;

    // Do the arc trace
    FPredictProjectilePathResult PredictResult;
    bool bHit = UGameplayStatics::PredictProjectilePath(this, Params, PredictResult);

    // Show Target Marker (if a valid teleport location)
    if (bHit)
    {
        TargetLocation = GetWorld()->GetNavigationSystem()->ProjectPointToNavigation(
            this,
            PredictResult.HitResult.Location,
            (ANavigationData*)0, 0,
            BeamHitNavMeshTolerance);

        // Check if arc hit location is within the nav mesh
        if (!PredictResult.HitResult.Location.Equals(TargetLocation, 0.0001f))
        {
            TargetLocation = PredictResult.HitResult.Location;
            TargetRotation = UKismetMathLibrary::FindLookAtRotation(TargetLocation, GetOwner()->GetActorLocation());
            SetTargetMarkerLocationAndRotation(TargetLocation, TargetRotation);

            // Set Target Marker Visibility
            SetTargetMarkerVisibility(true);
            bIsTargetLocationValid = true;
        }
        else
        {
            // Set Target Marker Visibility
            SetTargetMarkerVisibility(false);
            bIsTargetLocationValid = false;
        }
    }
    else
    {
        // Set Target Marker Visibility
        SetTargetMarkerVisibility(false);
        bIsTargetLocationValid = false;
    }


    // Set the teleport arc points
    if (ArcSpline)
    {
        // Clean-up old Spline
        ClearTeleportArc();

        // Set the point type for the curve
        ArcSpline->SetSplinePointType(ArcPoints.Num() - 1, ESplinePointType::CurveClamped, true);

        for (const FPredictProjectilePathPointData& PathPoint : PredictResult.PathData)
        {
            // Add the point to the arc spline
            ArcPoints.Add(PathPoint.Location);
            ArcSpline->AddSplinePoint(PathPoint.Location, ESplineCoordinateSpace::Local, true);
        }
    }

    // Populate arc points with meshes
    if (TeleportBeamMesh)
    {
        for (int32 i = 0; i < ArcPoints.Num() - 2; i++)
        {
            // Add the arc mesh
            USplineMeshComponent* ArcMesh = NewObject(ArcSpline);
            ArcMesh->RegisterComponentWithWorld(GetWorld());
            ArcMesh->SetMobility(EComponentMobility::Movable);
            //ArcMesh->AttachToComponent(ArcSpline, FAttachmentTransformRules::KeepRelativeTransform);
            ArcMesh->SetStaticMesh(TeleportBeamMesh);
            ArcSplineMeshes.Add(ArcMesh);

            // Bend mesh to conform to arc
            ArcMesh->SetStartAndEnd(ArcPoints[i],
                ArcSpline->GetTangentAtSplinePoint(i, ESplineCoordinateSpace::Local),
                ArcPoints[i + 1],
                ArcSpline->GetTangentAtSplinePoint(i + 1, ESplineCoordinateSpace::Local),
                true);
        }
    }

}

// Clear Teleport arc
void URunebergVR_Teleporter::ClearTeleportArc()
{
    // Clear Arc
    ArcPoints.Empty();
    ArcSpline->ClearSplinePoints();

    for (int32 i = 0; i < ArcSplineMeshes.Num(); i++)
    {
        if (ArcSplineMeshes[i])
        {
            ArcSplineMeshes[i]->DestroyComponent();
        }
    }

    ArcSplineMeshes.Empty();
}

// Show the teleportation arc trace
bool URunebergVR_Teleporter::ShowTeleportArc()
{
    if (!IsTeleporting)
    {
        TeleportMode = 0;
        IsTeleporting = true;
        bIsBeamTypeTeleport = true;
        SpawnTargetMarker();
        return true;
    }

    return false;
}

// Remove the teleportation arc trace
bool URunebergVR_Teleporter::HideTeleportArc()
{
    if (IsTeleporting)
    {
        TeleportMode = -1;
        IsTeleporting = false;
        bIsBeamTypeTeleport = false;
        ClearTeleportArc();

        // Clear Target Marker
        RemoveTargetMarker();

        return true;
    }

    return false;
}

// Remove the teleportation ray trace
bool URunebergVR_Teleporter::HideTeleportRay()
{
    if (IsTeleporting)
    {
        TeleportMode = -1;
        IsTeleporting = false;
        bIsBeamTypeTeleport = false;
        ClearTeleportRay();
        RayMeshScale = FVector(1.0f, 1.0f, 1.0f);

        // Clear Target Marker
        RemoveTargetMarker();

        return true;
    }

    return false;
}

// Clear Teleport ray
void URunebergVR_Teleporter::ClearTeleportRay()
{
    if (RayMesh)
    {
        // Remove ray mesh component
        RayMesh->DestroyComponent();
        RayMesh = nullptr;
    }
}

// Draw Teleport Ray
void URunebergVR_Teleporter::DrawTeleportRay()
{

    // Setup ray trace
    FCollisionQueryParams Ray_TraceParams(FName(TEXT("Ray_Trace")), true, this->GetOwner());
    Ray_TraceParams.bTraceComplex = true;
    Ray_TraceParams.bTraceAsyncScene = true;
    Ray_TraceParams.bReturnPhysicalMaterial = false;

    // Initialize Hit Result var
    FHitResult Ray_Hit(ForceInit);

    // Get Target Location
    TargetLocation = FVector(GetAttachParent()->GetComponentLocation().X + BeamLocationOffset.X,
        GetAttachParent()->GetComponentLocation().Y + BeamLocationOffset.Y,
        GetAttachParent()->GetComponentLocation().Z + BeamLocationOffset.Z) +
        (GetAttachParent()->GetComponentRotation().Vector() * BeamMagnitude);

    // Do the ray trace
    bool bHit = GetWorld()->LineTraceSingleByObjectType(
        Ray_Hit,
        GetAttachParent()->GetComponentLocation(),
        FVector(GetAttachParent()->GetComponentLocation().X + BeamLocationOffset.X,
            GetAttachParent()->GetComponentLocation().Y + BeamLocationOffset.Y,
            GetAttachParent()->GetComponentLocation().Z + BeamLocationOffset.Z) +
            (GetAttachParent()->GetComponentRotation().Vector() * BeamMagnitude),
        ECC_WorldStatic,
        Ray_TraceParams
    );


    // Reset Target Marker
    SetTargetMarkerVisibility(false);
    bIsTargetLocationValid = false;

    // Check if we hit a possible location to teleport to
    if (bHit)
    {
        // Check if target location is within the nav mesh
        FVector tempTargetLocation = GetWorld()->GetNavigationSystem()->ProjectPointToNavigation(
            this,
            Ray_Hit.ImpactPoint,
            (ANavigationData*)0, 0,
            BeamHitNavMeshTolerance);

        if (!tempTargetLocation.Equals(Ray_Hit.ImpactPoint, 0.0001f))
        {
            // Set Target Marker Visibility
            TargetLocation = Ray_Hit.ImpactPoint;
            TargetRotation = UKismetMathLibrary::FindLookAtRotation(TargetLocation, GetOwner()->GetActorLocation());
            SetTargetMarkerLocationAndRotation(TargetLocation, TargetRotation);
            SetTargetMarkerVisibility(true);
            bIsTargetLocationValid = true;
        }
    }

    // Draw ray mesh
    ClearTeleportRay();
    if (TeleportBeamMesh)
    {
        // Spawn the beam mesh
        RayMesh = NewObject(GetAttachParent());
        RayMesh->RegisterComponentWithWorld(GetWorld());
        RayMesh->SetMobility(EComponentMobility::Movable);
        RayMesh->AttachToComponent(GetAttachParent(), FAttachmentTransformRules::KeepRelativeTransform);
        RayMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
        RayMesh->SetStaticMesh(TeleportBeamMesh);
        RayMesh->AddLocalOffset(BeamLocationOffset);
        RayMesh->SetWorldRotation(UKismetMathLibrary::FindLookAtRotation(FVector(GetAttachParent()->GetComponentLocation().X + BeamLocationOffset.X,
            GetAttachParent()->GetComponentLocation().Y + BeamLocationOffset.Y,
            GetAttachParent()->GetComponentLocation().Z + BeamLocationOffset.Z), TargetLocation));

        // Scale the beam mesh
        if (RayInstantScale)
        {
            // Calculate how long the beam should be using RayScaleRate as the base unit
            RayMeshScale = FVector(FVector::Distance(GetComponentLocation(), TargetLocation) * RayScaleRate, 1.f, 1.f);
            RayMesh->SetWorldScale3D(RayMeshScale);
        }
        else
        {
            // Scale beam mesh gradually until it reaches the target location
            RayDistanceToTarget = FVector::Distance(GetComponentLocation(), TargetLocation);
            RayNumOfTimesToScale = RayDistanceToTarget;
            if (RayNumOfTimesToScale_Actual < RayNumOfTimesToScale)
            {
                // We haven't reached the target location yet, set the mesh scale
                RayMesh->SetWorldScale3D(RayMeshScale);
                RayMeshScale.X = RayMeshScale.X + RayScaleRate;

                // Update temp scale variables
                RayMeshScale_Max = RayMeshScale;
                RayNumOfTimesToScale_Actual += RayScaleRate;
            }
            else
            {
                // Scale mesh to max possible size to hit target location
                RayMesh->SetWorldScale3D(RayMeshScale_Max);
            }
        }
    }
}

// Show the teleportation ray trace
bool URunebergVR_Teleporter::ShowTeleportRay()
{
    if (!IsTeleporting)
    {
        TeleportMode = 1;
        IsTeleporting = true;
        bIsBeamTypeTeleport = true;
        SpawnTargetMarker();
        RayNumOfTimesToScale_Actual = 0.f;

        return true;
    }

    return false;
}

// Teleport object
bool URunebergVR_Teleporter::TeleportNow()
{
    // Only teleport if targetting is enabled
    if (IsTeleporting && bIsTargetLocationValid) {

        // Teleport
        GetAttachParent()->GetOwner()->SetActorLocation(TargetLocation + PawnHeightOffset + TeleportTargetPawnSpawnOffset, false, nullptr, ETeleportType::None);

        // Remove teleport artifacts
        switch (TeleportMode)
        {
        case 0:
            HideTeleportArc();
            break;

        case 1:
            HideTeleportRay();
            break;

        case 2:
            HideMarker();

        default:
            break;
        }

        // Reset Teleport mode
        TeleportMode = -1;

        return true;

    }

    return false;
}

// Show the teleport target marker
bool URunebergVR_Teleporter::ShowMarker()
{
    if (!IsTeleporting)
    {
        // Calculate Target Location
        TargetLocation = GetAttachParent()->GetComponentLocation() + (GetAttachParent()->GetComponentRotation().Vector() * BeamMagnitude);

        // Check if target location is within the nav mesh
        FVector tempTargetLocation = GetWorld()->GetNavigationSystem()->ProjectPointToNavigation(
            this,
            TargetLocation,
            (ANavigationData*)0, 0,
            BeamHitNavMeshTolerance);

        if (!tempTargetLocation.Equals(TargetLocation, 0.0001f))
        {
            // Set Target Marker Visibility
            TargetRotation = UKismetMathLibrary::FindLookAtRotation(TargetLocation, GetOwner()->GetActorLocation());
            SetTargetMarkerLocationAndRotation(TargetLocation, TargetRotation);
            SetTargetMarkerVisibility(true);
            bIsTargetLocationValid = true;
        }
        else
        {
            return false;
        }

        // Set teleport parameters
        TeleportMode = 2;
        IsTeleporting = true;
        bIsBeamTypeTeleport = false;
        bIsTargetLocationValid = true;

        // Show target marker
        SpawnTargetMarker();
        TargetRotation = UKismetMathLibrary::FindLookAtRotation(TargetLocation, GetOwner()->GetActorLocation());
        TargetLocation.Z = FloorIsAtZ;

        // Calculate Rotation of marker to face player and set the new transform
        SetTargetMarkerLocationAndRotation(TargetLocation, TargetRotation);

        // Make target marker visible
        SetTargetMarkerVisibility(true);

        return true;
    }

    return false;
}

// Remove Marker
bool URunebergVR_Teleporter::HideMarker()
{
    if (IsTeleporting)
    {
        TeleportMode = -1;
        IsTeleporting = false;
        bIsBeamTypeTeleport = false;
        bIsTargetLocationValid = false;

        // Clear Target Marker
        RemoveTargetMarker();

        return true;
    }

    return false;
}

// Move marker
bool URunebergVR_Teleporter::MoveMarker(EMoveDirectionEnum MarkerDirection, int Rate, FRotator CustomDirection)
{
    // Only move marker if it is visible and active
    if (IsTeleporting) {

        switch (MarkerDirection)
        {
        case  EMoveDirectionEnum::MOVE_FORWARD:
            TargetLocation = FVector(TargetLocation + (TargetRotation.Vector() * Rate));
            TargetLocation.Z = FloorIsAtZ;
            SetTargetMarkerLocationAndRotation(TargetLocation, TargetRotation);
            break;

        case  EMoveDirectionEnum::MOVE_BACKWARD:
            TargetLocation = TargetLocation + (TargetRotation.Vector() * -Rate);
            TargetLocation.Z = FloorIsAtZ;
            SetTargetMarkerLocationAndRotation(TargetLocation, TargetRotation);
            break;

        case  EMoveDirectionEnum::MOVE_LEFT:
            // Tilt original marker location to point Westwards
            CustomDirection = TargetRotation;
            CustomDirection.Yaw += 90.0f;

            // Calculate target location 
            TargetLocation = TargetLocation + (CustomDirection.Vector() * Rate);
            TargetLocation.Z = FloorIsAtZ;
            SetTargetMarkerLocationAndRotation(TargetLocation, TargetRotation);
            break;

        case  EMoveDirectionEnum::MOVE_RIGHT:
            // Tilt original marker location to point Eastwards
            CustomDirection = TargetRotation;
            CustomDirection.Yaw += 90.0f;

            // Calculate target location 
            TargetLocation = TargetLocation + (CustomDirection.Vector() * -Rate);
            TargetLocation.Z = FloorIsAtZ;
            SetTargetMarkerLocationAndRotation(TargetLocation, FRotator::ZeroRotator);
            break;

        case  EMoveDirectionEnum::MOVE_CUSTOM:
            TargetLocation = FVector(TargetLocation + (CustomDirection.Vector() * Rate));
            TargetLocation.Z = FloorIsAtZ;
            SetTargetMarkerLocationAndRotation(TargetLocation, TargetRotation);
            break;

        default:
            break;
        }

        return true;
    }

    return false;
}

// Show target location marker
void URunebergVR_Teleporter::SpawnTargetMarker(FVector MarkerLocation, FRotator MarkerRotation)
{
    // Activate Particle System if available
    if (TeleportTargetParticle) {
        TargetParticleSystemComponent = UGameplayStatics::SpawnEmitterAtLocation(this, TeleportTargetParticle, MarkerLocation, MarkerRotation);
        TargetParticleSystemComponent->SetWorldScale3D(TeleportTargetParticleScale);
        TargetParticleSystemComponent->SetVisibility(false);
        TargetParticleSystemComponent->SetMobility(EComponentMobility::Movable);
    }

    // Show Static Mesh if available
    if (TeleportTargetMesh) {
        // Create new static mesh component and attach to actor
        TargetStaticMeshComponent = NewObject(this);
        TargetStaticMeshComponent->RegisterComponentWithWorld(GetWorld());
        TargetStaticMeshComponent->SetSimulatePhysics(false);
        TargetStaticMeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
        TargetStaticMeshComponent->SetMobility(EComponentMobility::Movable);
        TargetStaticMeshComponent->AttachToComponent(GetOwner()->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);

        //Set Mesh
        TargetStaticMeshComponent->SetVisibility(false);
        TargetStaticMeshComponent->SetWorldScale3D(TeleportTargetMeshScale);
        TargetStaticMeshComponent->SetStaticMesh(TeleportTargetMesh);
    }
}

// Remove target location marker
void URunebergVR_Teleporter::RemoveTargetMarker()
{
    // Destroy Particle System if available
    if (TargetParticleSystemComponent) {
        TargetParticleSystemComponent->DestroyComponent();
        TargetParticleSystemComponent = nullptr;
    }

    // Destroy Static Mesh if available
    if (TargetStaticMeshComponent) {
        TargetStaticMeshComponent->DestroyComponent();
        TargetStaticMeshComponent = nullptr;
    }

    bIsTargetLocationValid = false;
}

// Show target location marker
void  URunebergVR_Teleporter::SetTargetMarkerVisibility(bool MakeVisible)
{
    // Activate Particle System if available
    if (TargetParticleSystemComponent) {
        TargetParticleSystemComponent->SetVisibility(MakeVisible);
    }

    // Show Static Mesh if available
    if (TargetStaticMeshComponent) {
        TargetStaticMeshComponent->SetVisibility(MakeVisible);
    }
}

// Move target location marker
void  URunebergVR_Teleporter::SetTargetMarkerLocationAndRotation(FVector MarkerLocation, FRotator MarkerRotation)
{
    // Activate Particle System if available
    if (TargetParticleSystemComponent) {
        TargetParticleSystemComponent->SetWorldLocation(MarkerLocation + TeleportTargetParticleSpawnOffset);
        TargetParticleSystemComponent->SetWorldRotation(MarkerRotation);
    }

    // Show Static Mesh if available
    if (TargetStaticMeshComponent) {
        TargetStaticMeshComponent->SetWorldLocation(MarkerLocation + TeleportTargetMeshSpawnOffset);
        TargetStaticMeshComponent->SetWorldRotation(MarkerRotation);
    }
}

以为这样就可以在蓝图里调用了吗,还不能,我们得干点别的事情哦
找到工程配置例如我的如图
UE4 VR 瞬移 Teleport 一_第2张图片
讲PublicDependencyModuleNames.AddRange()内容改为如图
好了 现在就可以调用了

你可能感兴趣的:(ue,vr)