200 lines
9.0 KiB
C++
200 lines
9.0 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "UObject/ObjectMacros.h"
|
|
#include "Engine/EngineTypes.h"
|
|
#include "Components/ActorComponent.h"
|
|
#include "PawnSensingComponent.generated.h"
|
|
|
|
class AActor;
|
|
class AController;
|
|
class APawn;
|
|
class UPawnNoiseEmitterComponent;
|
|
|
|
/**
|
|
* SensingComponent encapsulates sensory (ie sight and hearing) settings and functionality for an Actor,
|
|
* allowing the actor to see/hear Pawns in the world. It does nothing on network clients.
|
|
*/
|
|
class UE_DEPRECATED_FORGAME(5.5, "Pawn sensing is deprecated. AI Perception should be used instead.") UPawnSensingComponent;
|
|
UCLASS(ClassGroup=AI, HideCategories=(Activation, "Components|Activation", Collision), meta=(BlueprintSpawnableComponent), MinimalAPI)
|
|
class UPawnSensingComponent : public UActorComponent
|
|
{
|
|
GENERATED_UCLASS_BODY()
|
|
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( FSeePawnDelegate, APawn*, Pawn );
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( FHearNoiseDelegate, APawn*, Instigator, const FVector&, Location, float, Volume);
|
|
|
|
/** Max distance at which a makenoise(1.0) loudness sound can be heard, regardless of occlusion */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=AI)
|
|
float HearingThreshold;
|
|
|
|
/** Max distance at which a makenoise(1.0) loudness sound can be heard if unoccluded (LOSHearingThreshold should be > HearingThreshold) */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=AI)
|
|
float LOSHearingThreshold;
|
|
|
|
/** Maximum sight distance. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=AI)
|
|
float SightRadius;
|
|
|
|
/** Amount of time between pawn sensing updates. Use SetSensingInterval() to adjust this at runtime. A value <= 0 prevents any updates. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=AI)
|
|
float SensingInterval;
|
|
|
|
// Max age of sounds we can hear. Should be greater than SensingInterval, or you might miss hearing some sounds!
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=AI)
|
|
float HearingMaxSoundAge;
|
|
|
|
public:
|
|
|
|
/**
|
|
* Changes the SensingInterval.
|
|
* If we are currently waiting for an interval, this can either extend or shorten that interval.
|
|
* A value <= 0 prevents any updates.
|
|
*/
|
|
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="AI|Components|PawnSensing")
|
|
AIMODULE_API virtual void SetSensingInterval(const float NewSensingInterval);
|
|
|
|
/** Enables or disables sensing updates. The timer is reset in either case. */
|
|
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="AI|Components|PawnSensing")
|
|
AIMODULE_API virtual void SetSensingUpdatesEnabled(const bool bEnabled);
|
|
|
|
/** Sets PeripheralVisionAngle. Calculates PeripheralVisionCosine from PeripheralVisionAngle */
|
|
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="AI|Components|PawnSensing")
|
|
AIMODULE_API virtual void SetPeripheralVisionAngle(const float NewPeripheralVisionAngle);
|
|
|
|
UFUNCTION(BlueprintCallable, Category="AI|Components|PawnSensing")
|
|
float GetPeripheralVisionAngle() const;
|
|
|
|
UFUNCTION(BlueprintCallable, Category="AI|Components|PawnSensing")
|
|
float GetPeripheralVisionCosine() const;
|
|
|
|
/** If true, component will perform sensing updates. At runtime change this using SetSensingUpdatesEnabled(). */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=AI)
|
|
uint32 bEnableSensingUpdates:1;
|
|
|
|
/** If true, will only sense player-controlled pawns in the world. Default: true */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=AI)
|
|
uint32 bOnlySensePlayers:1;
|
|
|
|
/** If true, we will perform visibility tests and will trigger notifications when a Pawn is visible. Default: true */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=AI)
|
|
uint32 bSeePawns:1;
|
|
|
|
/**
|
|
* If true, we will perform audibility tests and will be notified when a Pawn makes a noise that can be heard. Default: true
|
|
* IMPORTANT NOTE: If we can see pawns (bSeePawns is true), and the pawn is visible, noise notifications are not triggered.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=AI)
|
|
uint32 bHearNoises:1;
|
|
|
|
/** Is the given actor our owner? Used to ensure that we are not trying to sense our self / our owner. */
|
|
AIMODULE_API virtual bool IsSensorActor(const AActor* Actor) const;
|
|
|
|
/** Are we capable of sensing anything (and do we have any callbacks that care about sensing)? If so UpdateAISensing() will be called every sensing interval. */
|
|
AIMODULE_API virtual bool CanSenseAnything() const;
|
|
|
|
/** Returns true if we should check whether the given Pawn is visible (because we can see things, the Pawn is not hidden, and if the Pawn is a player and we only see players) */
|
|
AIMODULE_API virtual bool ShouldCheckVisibilityOf(APawn* Pawn) const;
|
|
|
|
/**
|
|
* Chance of seeing other pawn decreases with increasing distance or angle in peripheral vision
|
|
* @param bMaySkipChecks if true allows checks to be sometimes skipped if target is far away (used by periodic automatic visibility checks)
|
|
* @return true if the specified pawn Other is potentially visible (within peripheral vision, etc.) - still need to do LineOfSightTo() check to see if actually visible.
|
|
*/
|
|
AIMODULE_API virtual bool CouldSeePawn(const APawn* Other, bool bMaySkipChecks = false) const;
|
|
|
|
/** Returns true if we should check whether we can hear the given Pawn (because we are able to hear, and the Pawn has the correct team relationship to us) */
|
|
AIMODULE_API virtual bool ShouldCheckAudibilityOf(APawn* Pawn) const;
|
|
|
|
/**
|
|
* Check line to other actor.
|
|
* @param Other is the actor whose visibility is being checked.
|
|
* @param ViewPoint is eye position visibility is being checked from.
|
|
* @return true if controller's pawn can see Other actor.
|
|
*/
|
|
AIMODULE_API virtual bool HasLineOfSightTo(const AActor* Other) const;
|
|
|
|
/** Test whether the noise is loud enough and recent enough to care about. bSourceWithinNoiseEmitter is true iff the
|
|
* noise was made by the pawn itself or within close proximity (its collision volume). Otherwise the noise was made
|
|
* at significant distance from the pawn.
|
|
*/
|
|
AIMODULE_API bool IsNoiseRelevant(const APawn& Pawn, const UPawnNoiseEmitterComponent& NoiseEmitterComponent, bool bSourceWithinNoiseEmitter) const;
|
|
|
|
/** @Returns true if sensor can hear this noise. Only executed if the noise has been determined to be relevant (via IsNoiseRelevant) */
|
|
AIMODULE_API virtual bool CanHear(const FVector& NoiseLoc, float Loudness, bool bFailedLOS) const;
|
|
|
|
//~ Begin UActorComponent Interface.
|
|
AIMODULE_API virtual void InitializeComponent() override;
|
|
//~ End UActorComponent Interface.
|
|
|
|
/** Get position where hearing/seeing occurs (i.e. ear/eye position). If we ever need different positions for hearing/seeing, we'll deal with that then! */
|
|
AIMODULE_API virtual FVector GetSensorLocation() const;
|
|
|
|
/** Get the rotation of this sensor. We need this for the sight component */
|
|
AIMODULE_API virtual FRotator GetSensorRotation() const;
|
|
|
|
protected:
|
|
|
|
/** See if there are interesting sounds and sights that we want to detect, and respond to them if so. */
|
|
AIMODULE_API virtual void SensePawn(APawn& Pawn);
|
|
|
|
/** Update function called on timer intervals. */
|
|
AIMODULE_API virtual void OnTimer();
|
|
|
|
/** Handle for efficient management of OnTimer timer */
|
|
FTimerHandle TimerHandle_OnTimer;
|
|
|
|
/** Modify the timer to fire in TimeDelay seconds. A value <= 0 disables the timer. */
|
|
AIMODULE_API virtual void SetTimer(const float TimeDelay);
|
|
|
|
/** Calls SensePawn on any Pawns that we are allowed to sense. */
|
|
AIMODULE_API virtual void UpdateAISensing();
|
|
|
|
AIMODULE_API AActor* GetSensorActor() const; // Get the actor used as the actual sensor location is derived from this actor.
|
|
AIMODULE_API AController* GetSensorController() const; // Get the controller of the sensor actor.
|
|
|
|
public:
|
|
/** Delegate to execute when we see a Pawn. */
|
|
UPROPERTY(BlueprintAssignable)
|
|
FSeePawnDelegate OnSeePawn;
|
|
|
|
/** Delegate to execute when we hear a noise from a Pawn's PawnNoiseEmitterComponent. */
|
|
UPROPERTY(BlueprintAssignable)
|
|
FHearNoiseDelegate OnHearNoise;
|
|
|
|
protected:
|
|
|
|
// Broadcasts notification that our sensor sees a Pawn, using the OnSeePawn delegates.
|
|
AIMODULE_API virtual void BroadcastOnSeePawn(APawn& Pawn);
|
|
|
|
// Broadcasts notification that our sensor hears a noise made local to a Pawn's position, using the OnHearNoise delegates.
|
|
AIMODULE_API virtual void BroadcastOnHearLocalNoise(APawn& Instigator, const FVector& Location, float Volume);
|
|
|
|
// Broadcasts notification that our sensor hears a noise made remotely from a Pawn's position, using the OnHearNoise delegates.
|
|
AIMODULE_API virtual void BroadcastOnHearRemoteNoise(APawn& Instigator, const FVector& Location, float Volume);
|
|
|
|
/** How far to the side AI can see, in degrees. Use SetPeripheralVisionAngle to change the value at runtime. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=AI)
|
|
float PeripheralVisionAngle;
|
|
|
|
/** Cosine of limits of peripheral vision. Computed from PeripheralVisionAngle. */
|
|
UPROPERTY()
|
|
float PeripheralVisionCosine;
|
|
};
|
|
|
|
|
|
|
|
inline float UPawnSensingComponent::GetPeripheralVisionAngle() const
|
|
{
|
|
return PeripheralVisionAngle;
|
|
}
|
|
|
|
inline float UPawnSensingComponent::GetPeripheralVisionCosine() const
|
|
{
|
|
return PeripheralVisionCosine;
|
|
}
|
|
|
|
|