A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
VRCharacter.cpp
Go to the documentation of this file.
1// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
2
3#include "VRCharacter.h"
4#include "NavigationSystem.h"
6//#include "Runtime/Engine/Private/EnginePrivate.h"
7
8DEFINE_LOG_CATEGORY(LogVRCharacter);
9
10AVRCharacter::AVRCharacter(const FObjectInitializer& ObjectInitializer)
11 : Super(ObjectInitializer.SetDefaultSubobjectClass<UVRRootComponent>(ACharacter::CapsuleComponentName).SetDefaultSubobjectClass<UVRCharacterMovementComponent>(ACharacter::CharacterMovementComponentName))
12{
13 VRRootReference = NULL;
14 if (GetCapsuleComponent())
15 {
16 VRRootReference = Cast<UVRRootComponent>(GetCapsuleComponent());
17 VRRootReference->SetCapsuleSize(20.0f, 96.0f);
18 //VRRootReference->VRCapsuleOffset = FVector(-8.0f, 0.0f, 0.0f);
19 VRRootReference->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
20 VRRootReference->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block);
21 }
22
24 if (GetMovementComponent())
25 {
26 VRMovementReference = Cast<UVRBaseCharacterMovementComponent>(GetMovementComponent());
27 //AddTickPrerequisiteComponent(this->GetCharacterMovement());
28 }
29}
30
31
32FVector AVRCharacter::GetTeleportLocation(FVector OriginalLocation)
33{
34 FVector modifier = VRRootReference->OffsetComponentToWorld.GetLocation() - this->GetActorLocation();
35 modifier.Z = 0.0f; // Null out Z
36 return OriginalLocation - modifier;
37}
38
39bool AVRCharacter::TeleportTo(const FVector& DestLocation, const FRotator& DestRotation, bool bIsATest, bool bNoCheck)
40{
41 bool bTeleportSucceeded = Super::TeleportTo(DestLocation, DestRotation, bIsATest, bNoCheck);
42
43 if (bTeleportSucceeded)
44 {
46 }
47
48 return bTeleportSucceeded;
49}
50
52{
53 FVector AgentLocation = FNavigationSystem::InvalidLocation;
54
55 if (GetCharacterMovement() != nullptr)
56 {
58 {
60 }
61 else
62 AgentLocation = GetCharacterMovement()->GetActorFeetLocation();
63 }
64
65 if (FNavigationSystem::IsValidLocation(AgentLocation) == false /*&& GetCapsuleComponent() != nullptr*/)
66 {
68 {
69 AgentLocation = VRRootReference->OffsetComponentToWorld.GetLocation() - FVector(0, 0, VRRootReference->GetScaledCapsuleHalfHeight());
70 }
71 else if(GetCapsuleComponent() != nullptr)
72 AgentLocation = GetActorLocation() - FVector(0, 0, GetCapsuleComponent()->GetScaledCapsuleHalfHeight());
73 }
74
75 return AgentLocation;
76}
77
78void AVRCharacter::ExtendedSimpleMoveToLocation(const FVector& GoalLocation, float AcceptanceRadius, bool bStopOnOverlap, bool bUsePathfinding, bool bProjectDestinationToNavigation, bool bCanStrafe, TSubclassOf<UNavigationQueryFilter> FilterClass, bool bAllowPartialPaths)
79{
80 UNavigationSystemV1* NavSys = Controller ? FNavigationSystem::GetCurrent<UNavigationSystemV1>(Controller->GetWorld()) : nullptr;
81 if (NavSys == nullptr || Controller == nullptr )
82 {
83 UE_LOG(LogVRCharacter, Warning, TEXT("UVRCharacter::ExtendedSimpleMoveToLocation called for NavSys:%s Controller:%s (if any of these is None then there's your problem"),
84 *GetNameSafe(NavSys), *GetNameSafe(Controller));
85 return;
86 }
87
88 UPathFollowingComponent* PFollowComp = nullptr;
89 //Controller->InitNavigationControl(PFollowComp);
90
91 if (Controller)
92 {
93 // New for 4.20, spawning the missing path following component here if there isn't already one
94 PFollowComp = Controller->FindComponentByClass<UPathFollowingComponent>();
95 if (PFollowComp == nullptr)
96 {
97 PFollowComp = NewObject<UVRPathFollowingComponent>(Controller);
98 PFollowComp->RegisterComponentWithWorld(Controller->GetWorld());
99 PFollowComp->Initialize();
100 }
101 }
102
103 if (PFollowComp == nullptr)
104 {
105 UE_LOG(LogVRCharacter, Warning, TEXT("ExtendedSimpleMoveToLocation - No PathFollowingComponent Found"));
106 return;
107 }
108
109 if (!PFollowComp->IsPathFollowingAllowed())
110 {
111 UE_LOG(LogVRCharacter, Warning, TEXT("ExtendedSimpleMoveToLocation - Path Following Movement Is Not Set To Allowed"));
112 return;
113 }
114
115 EPathFollowingReachMode ReachMode;
116 if (bStopOnOverlap)
117 ReachMode = EPathFollowingReachMode::OverlapAgent;
118 else
119 ReachMode = EPathFollowingReachMode::ExactLocation;
120
121 bool bAlreadyAtGoal = false;
122
123 if(UVRPathFollowingComponent * pathcomp = Cast<UVRPathFollowingComponent>(PFollowComp))
124 bAlreadyAtGoal = pathcomp->HasReached(GoalLocation, /*EPathFollowingReachMode::OverlapAgent*/ReachMode);
125 else
126 bAlreadyAtGoal = PFollowComp->HasReached(GoalLocation, /*EPathFollowingReachMode::OverlapAgent*/ReachMode);
127
128 // script source, keep only one move request at time
129 if (PFollowComp->GetStatus() != EPathFollowingStatus::Idle)
130 {
131 if (GetNetMode() == ENetMode::NM_Client)
132 {
133 // Stop the movement here, not keeping the velocity because it bugs out for clients, might be able to fix.
134 PFollowComp->AbortMove(*NavSys, FPathFollowingResultFlags::ForcedScript | FPathFollowingResultFlags::NewRequest
135 , FAIRequestID::AnyRequest, /*bAlreadyAtGoal ? */EPathFollowingVelocityMode::Reset /*: EPathFollowingVelocityMode::Keep*/);
136 }
137 else
138 {
139 PFollowComp->AbortMove(*NavSys, FPathFollowingResultFlags::ForcedScript | FPathFollowingResultFlags::NewRequest
140 , FAIRequestID::AnyRequest, bAlreadyAtGoal ? EPathFollowingVelocityMode::Reset : EPathFollowingVelocityMode::Keep);
141 }
142 }
143
144 if (bAlreadyAtGoal)
145 {
146 PFollowComp->RequestMoveWithImmediateFinish(EPathFollowingResult::Success);
147 }
148 else
149 {
150 const ANavigationData* NavData = NavSys->GetNavDataForProps(Controller->GetNavAgentPropertiesRef());
151 if (NavData)
152 {
153 FPathFindingQuery Query(Controller, *NavData, Controller->GetNavAgentLocation(), GoalLocation);
154 FPathFindingResult Result = NavSys->FindPathSync(Query);
155 if (Result.IsSuccessful())
156 {
157 FAIMoveRequest MoveReq(GoalLocation);
158 MoveReq.SetUsePathfinding(bUsePathfinding);
159 MoveReq.SetAllowPartialPath(bAllowPartialPaths);
160 MoveReq.SetProjectGoalLocation(bProjectDestinationToNavigation);
161 MoveReq.SetNavigationFilter(*FilterClass ? FilterClass : DefaultNavigationFilterClass);
162 MoveReq.SetAcceptanceRadius(AcceptanceRadius);
163 MoveReq.SetReachTestIncludesAgentRadius(bStopOnOverlap);
164 MoveReq.SetCanStrafe(bCanStrafe);
165 MoveReq.SetReachTestIncludesGoalRadius(true);
166
167 PFollowComp->RequestMove(/*FAIMoveRequest(GoalLocation)*/MoveReq, Result.Path);
168 }
169 else if (PFollowComp->GetStatus() != EPathFollowingStatus::Idle)
170 {
171 PFollowComp->RequestMoveWithImmediateFinish(EPathFollowingResult::Invalid);
172 }
173 }
174 }
175}
176
177void AVRCharacter::RegenerateOffsetComponentToWorld(bool bUpdateBounds, bool bCalculatePureYaw)
178{
179 if (VRRootReference)
180 {
181 VRRootReference->GenerateOffsetToWorld(bUpdateBounds, bCalculatePureYaw);
182 }
183}
184
185void AVRCharacter::SetCharacterSizeVR(float NewRadius, float NewHalfHeight, bool bUpdateOverlaps)
186{
187 if (VRRootReference)
188 {
189 VRRootReference->SetCapsuleSizeVR(NewRadius, NewHalfHeight, bUpdateOverlaps);
190
191 if (GetNetMode() < ENetMode::NM_Client)
192 ReplicatedCapsuleHeight.CapsuleHeight = VRRootReference->GetUnscaledCapsuleHalfHeight();
193 }
194 else
195 {
196 Super::SetCharacterSizeVR(NewRadius, NewHalfHeight, bUpdateOverlaps);
197 }
198}
199
200void AVRCharacter::SetCharacterHalfHeightVR(float HalfHeight, bool bUpdateOverlaps)
201{
202 if (VRRootReference)
203 {
204 VRRootReference->SetCapsuleHalfHeightVR(HalfHeight, bUpdateOverlaps);
205
206 if (GetNetMode() < ENetMode::NM_Client)
207 ReplicatedCapsuleHeight.CapsuleHeight = VRRootReference->GetUnscaledCapsuleHalfHeight();
208 }
209 else
210 {
211 Super::SetCharacterHalfHeightVR(HalfHeight, bUpdateOverlaps);
212 }
213}
DEFINE_LOG_CATEGORY(LogVRCharacter)
FVRReplicatedCapsuleHeight ReplicatedCapsuleHeight
UPROPERTY(Replicated, ReplicatedUsing = OnRep_CapsuleHeight)
UVRBaseCharacterMovementComponent * VRMovementReference
UPROPERTY(Category = VRBaseCharacter, VisibleAnywhere, Transient, BlueprintReadOnly,...
virtual void NotifyOfTeleport(bool bRegisterAsTeleport=true)
UFUNCTION(BlueprintCallable, Category = "VRGrip")
TSubclassOf< UNavigationQueryFilter > DefaultNavigationFilterClass
UPROPERTY(BlueprintReadWrite, Category = AI)
AVRCharacter(const FObjectInitializer &ObjectInitializer=FObjectInitializer::Get())
virtual bool TeleportTo(const FVector &DestLocation, const FRotator &DestRotation, bool bIsATest=false, bool bNoCheck=false) override
virtual void SetCharacterSizeVR(float NewRadius, float NewHalfHeight, bool bUpdateOverlaps=true) override
UFUNCTION(BlueprintCallable, Category = "BaseVRCharacter")
UVRRootComponent * VRRootReference
UPROPERTY(Category = VRCharacter, VisibleAnywhere, Transient, BlueprintReadOnly, meta = (AllowPrivate...
Definition VRCharacter.h:38
virtual FVector GetTeleportLocation(FVector OriginalLocation) override
UFUNCTION(BlueprintPure, Category = "VRGrip")
virtual void ExtendedSimpleMoveToLocation(const FVector &GoalLocation, float AcceptanceRadius=-1, bool bStopOnOverlap=false, bool bUsePathfinding=true, bool bProjectDestinationToNavigation=true, bool bCanStrafe=false, TSubclassOf< UNavigationQueryFilter > FilterClass=NULL, bool bAllowPartialPath=true) override
UFUNCTION(BlueprintCallable, Category = "VRBaseCharacter|Navigation", Meta = (AdvancedDisplay = "bSto...
virtual void RegenerateOffsetComponentToWorld(bool bUpdateBounds, bool bCalculatePureYaw) override
UFUNCTION(BlueprintCallable, Category = "BaseVRCharacter|VRLocations")
FVector GetNavAgentLocation() const override
virtual void SetCharacterHalfHeightVR(float HalfHeight, bool bUpdateOverlaps=true) override
UFUNCTION(BlueprintCallable, Category = "BaseVRCharacter")
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent), ClassGroup = VRExpansionLibrary)
FORCEINLINE void GenerateOffsetToWorld(bool bUpdateBounds=true, bool bGetPureYaw=true)
virtual void SetCapsuleSizeVR(float NewRadius, float NewHalfHeight, bool bUpdateOverlaps=true)
UFUNCTION(BlueprintCallable, Category = "Components|Capsule")
void SetCapsuleHalfHeightVR(float HalfHeight, bool bUpdateOverlaps=true)
UFUNCTION(BlueprintCallable, Category = "Components|Capsule")
FTransform OffsetComponentToWorld