虚幻C++基础 day3
常见的游戏机制
Actor机关门
-
创建一个Actor类,添加两个静态网格与一个触发器
- UBoxComponent
- UStaticMeshComponent
-
头文件:
- #include “Components/BoxComponent.h”
- #include “Components/StaticMeshComponent.h”
TriggerDoor.h
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TriggerDoor.generated.h"UCLASS()
class UEGAME_API ATriggerDoor : public AActor
{GENERATED_BODY()public: // Sets default values for this actor's propertiesATriggerDoor();UPROPERTY(VisibleAnywhere, BlueprintReadWrite)class UBoxComponent* TriggerBox;UPROPERTY(VisibleAnywhere, BlueprintReadWrite)class UStaticMeshComponent* TriggerMesh;UPROPERTY(VisibleAnywhere, BlueprintReadWrite)UStaticMeshComponent* DoorMesh;protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public: // Called every framevirtual void Tick(float DeltaTime) override;};
TriggerDoor.cpp
// Fill out your copyright notice in the Description page of Project Settings.#include "TriggerDoor.h"
#include "Components/BoxComponent.h"
#include "Components/StaticMeshComponent.h"
// Sets default values
ATriggerDoor::ATriggerDoor()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;TriggerBox = CreateDefaultSubobject<UBoxComponent>(TEXT("TriggerBox"));RootComponent = TriggerBox;TriggerMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TriggerMesh"));TriggerMesh->SetupAttachment(GetRootComponent());DoorMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorMesh"));DoorMesh->SetupAttachment(GetRootComponent());}// Called when the game starts or when spawned
void ATriggerDoor::BeginPlay()
{Super::BeginPlay();}// Called every frame
void ATriggerDoor::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}
设置材质上去
- 直接采用场景里面的材质附着上去即可

编写位置更新函数
- 修好好位置后点击这个就可以实例同步到蓝图中


蓝图中的时间轴函数(Timeline)与UE多播委托机制
多播委托
- 触发器中提供了两个与一个绑定宏用来判断组件是否被重叠,这两个函数是要参与UE反射系统的,我们需要使用UFUNCTION进行标明,UFUNCTION里面可以什么参数不要,我们称这个操作为多播委托
OnComponentBeginOverlap:事件,当某些内容开始与此组件重叠时调用,例如玩家进入触发器。OnComponentEndOverlap:事件,当组件停止重叠时调用
AddDynamic宏:这个宏需要传入一个绑定函数,绑定函数参数格式如下UE源码,因为UE是把参数与参数类型都当做参数了,所以我们需要把逗号删除,一般是从开头数字乘2,从参数最后面开始选择,例如:SixParams(...),也就是6*2=12个参数,从函数尾部开始复制12个参数,注意UE4.23之后的版本可能参数不一样
/*** Delegate for notification of blocking collision against a specific component. * NormalImpulse will be filled in for physics-simulating bodies, but will be zero for swept-component blocking collisions. */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FiveParams( FComponentHitSignature, UPrimitiveComponent*, HitComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, FVector, NormalImpulse, const FHitResult&, Hit );
/** Delegate for notification of start of overlap with a specific component */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_SixParams( FComponentBeginOverlapSignature, UPrimitiveComponent*, OverlappedComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, int32, OtherBodyIndex, bool, bFromSweep, const FHitResult &, SweepResult);
/** Delegate for notification of end of overlap with a specific component */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams( FComponentEndOverlapSignature, UPrimitiveComponent*, OverlappedComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, int32, OtherBodyIndex);
/** Delegate for notification when a wake event is fired by physics*/
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FComponentWakeSignature, UPrimitiveComponent*, WakingComponent, FName, BoneName);
/** Delegate for notification when a sleep event is fired by physics*/
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FComponentSleepSignature, UPrimitiveComponent*, SleepingComponent, FName, BoneName);
/** Delegate for notification when collision settings change. */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FComponentCollisionSettingsChangedSignature, UPrimitiveComponent*, ChangedComponent);DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( FComponentBeginCursorOverSignature, UPrimitiveComponent*, TouchedComponent );
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( FComponentEndCursorOverSignature, UPrimitiveComponent*, TouchedComponent );
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( FComponentOnClickedSignature, UPrimitiveComponent*, TouchedComponent , FKey, ButtonPressed);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( FComponentOnReleasedSignature, UPrimitiveComponent*, TouchedComponent, FKey, ButtonReleased);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( FComponentOnInputTouchBeginSignature, ETouchIndex::Type, FingerIndex, UPrimitiveComponent*, TouchedComponent );
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( FComponentOnInputTouchEndSignature, ETouchIndex::Type, FingerIndex, UPrimitiveComponent*, TouchedComponent );
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( FComponentBeginTouchOverSignature, ETouchIndex::Type, FingerIndex, UPrimitiveComponent*, TouchedComponent );
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( FComponentEndTouchOverSignature, ETouchIndex::Type, FingerIndex, UPrimitiveComponent*, TouchedComponent );
- 声明两个绑定函数
public: // Called every framevirtual void Tick(float DeltaTime) override;//自定义AddDynamic绑定的触发器函数UFUNCTION()void OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);UFUNCTION()void OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
};
- 将多播委托进行绑定
// Called when the game starts or when spawned
void ATriggerDoor::BeginPlay()
{Super::BeginPlay();//绑定事件TriggerBox->OnComponentBeginOverlap.AddDynamic(this, &ATriggerDoor::OnOverlapBegin);TriggerBox->OnComponentEndOverlap.AddDynamic(this, &ATriggerDoor::OnOverlapEnd);
}// Called every frame
void ATriggerDoor::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}void ATriggerDoor::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
}void ATriggerDoor::OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
}
指定触发器只响应Pawn
//设置TriggerBox碰撞的硬编码TriggerBox->SetCollisionEnabled(ECollisionEnabled::QueryOnly);//设置碰撞类型TriggerBox->SetCollisionObjectType(ECollisionChannel::ECC_WorldStatic);//设置对象移动时其应视为某种物体TriggerBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);//设置所有的碰撞响应为忽略TriggerBox->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Overlap);//设置Pawn碰撞响应为重叠
TriggerDoor.h
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TriggerDoor.generated.h"UCLASS()
class UEGAME_API ATriggerDoor : public AActor
{GENERATED_BODY()public: // Sets default values for this actor's propertiesATriggerDoor();UPROPERTY(VisibleAnywhere, BlueprintReadWrite)class UBoxComponent* TriggerBox;UPROPERTY(VisibleAnywhere, BlueprintReadWrite)class UStaticMeshComponent* TriggerMesh;UPROPERTY(VisibleAnywhere, BlueprintReadWrite)UStaticMeshComponent* DoorMesh;protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public: // Called every framevirtual void Tick(float DeltaTime) override;//自定义AddDynamic绑定的触发器函数UFUNCTION()void OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);UFUNCTION()void OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
};
TriggerDoor.cpp
// Fill out your copyright notice in the Description page of Project Settings.#include "TriggerDoor.h"
#include "Components/BoxComponent.h"
#include "Components/StaticMeshComponent.h"
#include "Characters/Player/MainPlayer.h"
// Sets default values
ATriggerDoor::ATriggerDoor()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;TriggerBox = CreateDefaultSubobject<UBoxComponent>(TEXT("TriggerBox"));RootComponent = TriggerBox;TriggerBox->SetBoxExtent(FVector(60.f, 60.f, 30.f));//设置TriggerBox碰撞的硬编码TriggerBox->SetCollisionEnabled(ECollisionEnabled::QueryOnly);//设置碰撞类型TriggerBox->SetCollisionObjectType(ECollisionChannel::ECC_WorldStatic);//设置对象移动时其应视为某种物体TriggerBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);//设置所有的碰撞响应为忽略TriggerBox->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Overlap);//设置Pawn碰撞响应为重叠TriggerMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TriggerMesh"));TriggerMesh->SetupAttachment(GetRootComponent());DoorMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorMesh"));DoorMesh->SetupAttachment(GetRootComponent());}// Called when the game starts or when spawned
void ATriggerDoor::BeginPlay()
{Super::BeginPlay();TriggerBox->OnComponentBeginOverlap.AddDynamic(this, &ATriggerDoor::OnOverlapBegin);TriggerBox->OnComponentEndOverlap.AddDynamic(this, &ATriggerDoor::OnOverlapEnd);
}// Called every frame
void ATriggerDoor::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}void ATriggerDoor::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{AMainPlayer* Player = Cast<AMainPlayer>(OtherActor);if (Player){}
}void ATriggerDoor::OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{AMainPlayer* Player = Cast<AMainPlayer>(OtherActor);if (Player){}
}
BlueprintImplementableEvent参数的使用
- 新建几个函数用来升起降下门,关闭打开门
- BlueprintImplementableEvent:会把函数变成一个事件,把函数提升为事件后,就不能去初始化函数了,因为这个是在蓝图调用的事件




编写更新函数在蓝图中使用
- 新建两个用于更新的函数在蓝图中调用,新建两个变量用来获取当前门与触发器的offset,用于更新函数中去进行位置移动
//获取门与触发器位置
UPROPERTY(BluerprintReadWrite,Category = "Trigger Door|Trigger Properties")
FVector InitTriggerLoction;
UPROPERTY(BluerprintReadWrite,Category = "Trigger Door|Door Properties")
FVector InitDoorLocation;
UFUNCTION(BlueprintCallable,Category="Triggerable Door | Triggerable Switch")
void UpdateTriggerLocation(FVector offset);
UFUNCTION(BlueprintCallabel,Category= "Triggerable Door | Door Switch")
void UpdateDoorLocation(FVector offset);
- 在BeginPlay中初始化门和触发器的位置
// Called when the game starts or when spawned
void ATriggerDoor::BeginPlay()
{Super::BeginPlay();TriggerBox->OnComponentBeginOverlap.AddDynamic(this, &ATriggerDoor::OnOverlapBegin);TriggerBox->OnComponentEndOverlap.AddDynamic(this, &ATriggerDoor::OnOverlapEnd);//获取到门和触发器的位置InitTriggerLoction = TriggerMesh->GetComponentLocation();InitDoorLocation = DoorMesh->GetComponentLocation();
}
- 然后去更新函数中更新门与触发器的位置
void ATriggerDoor::UpdateTriggerLocation(FVector offset)
{//新位置=初始位置+移动后的位置FVector newLocation = InitTriggerLoction + offset;TriggerMesh->SetWorldLocation(newLocation);
}void ATriggerDoor::UpdateDoorLocation(FVector offset)
{//新位置=初始位置+移动后的位置FVector newLocation = InitDoorLocation + offset;DoorMesh->SetWorldLocation(newLocation);
}
- 然后去蓝图中连接更新函数

采用定时器关门
- 采用定时器关门的两种思路:
- 思路一:我们可以在人物踩上触发器的时候开启定时器进行关门,当人物离开定时器的时候就关闭定时器
- 思路二:我们可以定义一个bool变量(默认为false)进行判断定时器是否开启,当人物踩上触发器的时候就让变量为true,当人物离开触发器的时候就为false也就不执行定时器
- 定时器头文件:#include “TimerManager.h”
FTimerHandleCloseDoorTimerHandle: 创建一个时间句柄- SetTimer的六个重载函数
/*** Sets a timer to call the given native function at a set interval. If a timer is already set* for this handle, it will replace the current timer.** @param InOutHandle If the passed-in handle refers to an existing timer, it will be cleared before the new timer is added. A new handle to the new timer is returned in either case.* @param InObj Object to call the timer function on.* @param InTimerMethod Method to call when timer fires.* @param InRate The amount of time between set and firing. If <= 0.f, clears existing timers.* @param InbLoop true to keep firing at Rate intervals, false to fire only once.* @param InFirstDelay The time for the first iteration of a looping timer. If < 0.f inRate will be used.*/template< class UserClass >FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, UserClass* InObj, typename FTimerDelegate::TUObjectMethodDelegate< UserClass >::FMethodPtr InTimerMethod, float InRate, bool InbLoop = false, float InFirstDelay = -1.f){InternalSetTimer(InOutHandle, FTimerUnifiedDelegate( FTimerDelegate::CreateUObject(InObj, InTimerMethod) ), InRate, InbLoop, InFirstDelay);}template< class UserClass >FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, UserClass* InObj, typename FTimerDelegate::TUObjectMethodDelegate_Const< UserClass >::FMethodPtr InTimerMethod, float InRate, bool InbLoop = false, float InFirstDelay = -1.f){InternalSetTimer(InOutHandle, FTimerUnifiedDelegate( FTimerDelegate::CreateUObject(InObj, InTimerMethod) ), InRate, InbLoop, InFirstDelay);}/** Version that takes any generic delegate. */FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, FTimerDelegate const& InDelegate, float InRate, bool InbLoop, float InFirstDelay = -1.f){InternalSetTimer(InOutHandle, FTimerUnifiedDelegate(InDelegate), InRate, InbLoop, InFirstDelay);}/** Version that takes a dynamic delegate (e.g. for UFunctions). */FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, FTimerDynamicDelegate const& InDynDelegate, float InRate, bool InbLoop, float InFirstDelay = -1.f){InternalSetTimer(InOutHandle, FTimerUnifiedDelegate(InDynDelegate), InRate, InbLoop, InFirstDelay);}/*** Version that doesn't take a delegate */FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, float InRate, bool InbLoop, float InFirstDelay = -1.f){InternalSetTimer(InOutHandle, FTimerUnifiedDelegate(), InRate, InbLoop, InFirstDelay);}/** Version that takes a TFunction */FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, TFunction<void(void)>&& Callback, float InRate, bool InbLoop, float InFirstDelay = -1.f ){InternalSetTimer(InOutHandle, FTimerUnifiedDelegate(MoveTemp(Callback)), InRate, InbLoop, InFirstDelay);}
思路一
- Trigger.h
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TriggerDoor.generated.h"UCLASS()
class UEGAME_API ATriggerDoor : public AActor
{GENERATED_BODY()public: // Sets default values for this actor's propertiesATriggerDoor();UPROPERTY(VisibleAnywhere, BlueprintReadWrite)class UBoxComponent* TriggerBox;UPROPERTY(VisibleAnywhere, BlueprintReadWrite)class UStaticMeshComponent* TriggerMesh;UPROPERTY(VisibleAnywhere, BlueprintReadWrite)UStaticMeshComponent* DoorMesh;//获取门与触发器位置UPROPERTY(BlueprintReadWrite,Category = "Trigger Door|Trigger Properties")FVector InitTriggerLoction;UPROPERTY(BlueprintReadWrite,Category = "Trigger Door|Door Properties")FVector InitDoorLocation;//延时时间UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Trigger Door|Trigger Properties")float DelayTimer;//创建一个时间句柄FTimerHandle CloseDoorTimerHandle;protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public: // Called every framevirtual void Tick(float DeltaTime) override;//自定义AddDynamic绑定的触发器函数UFUNCTION()void OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);UFUNCTION()void OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);//将函数提升为事件UFUNCTION(BlueprintImplementableEvent, Category = "Triggerable Dorr|Trigger Switch")void RaiseTrigger();UFUNCTION(BlueprintImplementableEvent, Category = "Triggerable Dorr|Trigger Switch")void LowerTrigger();UFUNCTION(BlueprintImplementableEvent, Category = "Triggerable Dorr|Trigger Switch")void OpenDoor();UFUNCTION(BlueprintImplementableEvent, Category = "Triggerable Dorr|Trigger Switch")void CloseDoor();UFUNCTION(BlueprintCallable,Category="Triggerable Door | Triggerable Switch")void UpdateTriggerLocation(FVector offset);UFUNCTION(BlueprintCallable,Category= "Triggerable Door | Door Switch")void UpdateDoorLocation(FVector offset);
};
- Trigger.cpp
// Fill out your copyright notice in the Description page of Project Settings.#include "TriggerDoor.h"
#include "Components/BoxComponent.h"
#include "Components/StaticMeshComponent.h"
#include "Characters/Player/MainPlayer.h"
#include "TimerManager.h"// Sets default values
ATriggerDoor::ATriggerDoor()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;TriggerBox = CreateDefaultSubobject<UBoxComponent>(TEXT("TriggerBox"));RootComponent = TriggerBox;TriggerBox->SetBoxExtent(FVector(60.f, 60.f, 30.f));//设置TriggerBox碰撞的硬编码TriggerBox->SetCollisionEnabled(ECollisionEnabled::QueryOnly);//设置碰撞类型TriggerBox->SetCollisionObjectType(ECollisionChannel::ECC_WorldStatic);//设置对象移动时其应视为某种物体TriggerBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);//设置所有的碰撞响应为忽略TriggerBox->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Overlap);//设置Pawn碰撞响应为重叠TriggerMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TriggerMesh"));TriggerMesh->SetupAttachment(GetRootComponent());DoorMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorMesh"));DoorMesh->SetupAttachment(GetRootComponent());//延迟时间设为2秒DelayTimer = 2.0f;}// Called when the game starts or when spawned
void ATriggerDoor::BeginPlay()
{Super::BeginPlay();TriggerBox->OnComponentBeginOverlap.AddDynamic(this, &ATriggerDoor::OnOverlapBegin);TriggerBox->OnComponentEndOverlap.AddDynamic(this, &ATriggerDoor::OnOverlapEnd);//获取到门和触发器的位置InitTriggerLoction = TriggerMesh->GetComponentLocation();InitDoorLocation = DoorMesh->GetComponentLocation();
}// Called every frame
void ATriggerDoor::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}void ATriggerDoor::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{AMainPlayer* Player = Cast<AMainPlayer>(OtherActor);if (Player){//清除定时器GetWorldTimerManager().ClearTimer(CloseDoorTimerHandle);OpenDoor();LowerTrigger();}
}void ATriggerDoor::OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{AMainPlayer* Player = Cast<AMainPlayer>(OtherActor);if (Player){RaiseTrigger();//开启定时器进行关门GetWorldTimerManager().SetTimer(CloseDoorTimerHandle, this, &ATriggerDoor::CloseDoor, DelayTimer);}
}void ATriggerDoor::UpdateTriggerLocation(FVector offset)
{//新位置=初始位置+移动后的位置FVector newLocation = InitTriggerLoction + offset;TriggerMesh->SetWorldLocation(newLocation);
}void ATriggerDoor::UpdateDoorLocation(FVector offset)
{//新位置=初始位置+移动后的位置FVector newLocation = InitDoorLocation + offset;DoorMesh->SetWorldLocation(newLocation);
}
思路二
- 定义一个bool变量用来检测角色是否踩到触发器
- 我们采用Lambda表示来进行操作,使用Lambda表达式操作,SetTimer函数传入参数会不一样
GetWorldTimerManager().SetTimer(CloseDoorTimerHandle, FTimerDelegate::CreateLambda(CloseDoorLambda), DelayTimer, false);

- Trigger.h
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TriggerDoor.generated.h"UCLASS()
class UEGAME_API ATriggerDoor : public AActor
{GENERATED_BODY()public: // Sets default values for this actor's propertiesATriggerDoor();UPROPERTY(VisibleAnywhere, BlueprintReadWrite)class UBoxComponent* TriggerBox;UPROPERTY(VisibleAnywhere, BlueprintReadWrite)class UStaticMeshComponent* TriggerMesh;UPROPERTY(VisibleAnywhere, BlueprintReadWrite)UStaticMeshComponent* DoorMesh;//获取门与触发器位置UPROPERTY(BlueprintReadWrite,Category = "Trigger Door|Trigger Properties")FVector InitTriggerLoction;UPROPERTY(BlueprintReadWrite,Category = "Trigger Door|Door Properties")FVector InitDoorLocation;//延时时间UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Trigger Door|Trigger Properties")float DelayTimer;bool bIsPlayerOnTrigger;//创建一个时间句柄FTimerHandle CloseDoorTimerHandle;protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public: // Called every framevirtual void Tick(float DeltaTime) override;//自定义AddDynamic绑定的触发器函数UFUNCTION()void OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);UFUNCTION()void OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);//将函数提升为事件UFUNCTION(BlueprintImplementableEvent, Category = "Triggerable Dorr|Trigger Switch")void RaiseTrigger();UFUNCTION(BlueprintImplementableEvent, Category = "Triggerable Dorr|Trigger Switch")void LowerTrigger();UFUNCTION(BlueprintImplementableEvent, Category = "Triggerable Dorr|Trigger Switch")void OpenDoor();UFUNCTION(BlueprintImplementableEvent, Category = "Triggerable Dorr|Trigger Switch")void CloseDoor();UFUNCTION(BlueprintCallable,Category="Triggerable Door | Triggerable Switch")void UpdateTriggerLocation(FVector offset);UFUNCTION(BlueprintCallable,Category= "Triggerable Door | Door Switch")void UpdateDoorLocation(FVector offset);
};
- Tirgger.cpp
// Fill out your copyright notice in the Description page of Project Settings.#include "TriggerDoor.h"
#include "Components/BoxComponent.h"
#include "Components/StaticMeshComponent.h"
#include "Characters/Player/MainPlayer.h"
#include "TimerManager.h"// Sets default values
ATriggerDoor::ATriggerDoor()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;TriggerBox = CreateDefaultSubobject<UBoxComponent>(TEXT("TriggerBox"));RootComponent = TriggerBox;TriggerBox->SetBoxExtent(FVector(60.f, 60.f, 30.f));//设置TriggerBox碰撞的硬编码TriggerBox->SetCollisionEnabled(ECollisionEnabled::QueryOnly);//设置碰撞类型TriggerBox->SetCollisionObjectType(ECollisionChannel::ECC_WorldStatic);//设置对象移动时其应视为某种物体TriggerBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);//设置所有的碰撞响应为忽略TriggerBox->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Overlap);//设置Pawn碰撞响应为重叠TriggerMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TriggerMesh"));TriggerMesh->SetupAttachment(GetRootComponent());DoorMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorMesh"));DoorMesh->SetupAttachment(GetRootComponent());//延迟时间设为2秒DelayTimer = 2.0f;bIsPlayerOnTrigger = false;
}// Called when the game starts or when spawned
void ATriggerDoor::BeginPlay()
{Super::BeginPlay();TriggerBox->OnComponentBeginOverlap.AddDynamic(this, &ATriggerDoor::OnOverlapBegin);TriggerBox->OnComponentEndOverlap.AddDynamic(this, &ATriggerDoor::OnOverlapEnd);//获取到门和触发器的位置InitTriggerLoction = TriggerMesh->GetComponentLocation();InitDoorLocation = DoorMesh->GetComponentLocation();
}// Called every frame
void ATriggerDoor::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}void ATriggerDoor::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{AMainPlayer* Player = Cast<AMainPlayer>(OtherActor);if (Player){//判断主角踩到触发器,就为真if (bIsPlayerOnTrigger == false){bIsPlayerOnTrigger = true;}OpenDoor();LowerTrigger();}
}void ATriggerDoor::OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{AMainPlayer* Player = Cast<AMainPlayer>(OtherActor);//判断主角没踩到触发器,就为假if (bIsPlayerOnTrigger == true){bIsPlayerOnTrigger = false;}//Lambda表达式auto CloseDoorLambda = [this](){//主角没有踩到触发器就关门if (bIsPlayerOnTrigger == false){CloseDoor();}};if(Player){RaiseTrigger();//开启定时器进行关门GetWorldTimerManager().SetTimer(CloseDoorTimerHandle, FTimerDelegate::CreateLambda(CloseDoorLambda), DelayTimer, false);}
}void ATriggerDoor::UpdateTriggerLocation(FVector offset)
{//新位置=初始位置+移动后的位置FVector newLocation = InitTriggerLoction + offset;TriggerMesh->SetWorldLocation(newLocation);
}void ATriggerDoor::UpdateDoorLocation(FVector offset)
{//新位置=初始位置+移动后的位置FVector newLocation = InitDoorLocation + offset;DoorMesh->SetWorldLocation(newLocation);
}
Actor创建一个随机生成空间
- 新建一个Actor类用来随机随机生成Actor,添加触发器与一个模版变量(专门用来存储AActor)
public: // Sets default values for this actor's propertiesASpawnVolume();//触发器UPROPERTY(VisibleAnywhere, BlueprintReadOnly)class UBoxComponent* SpawnBox;//模版类,用来添加AActorUPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Spawn Volume")TArray<TSubclassOf<AActor>> SpawnClass;
获取Actor随机位置与随机种类
- 新建两个函数用来获取种类与位置
- 头文件#include “Kismet/KismetMathLibrary.h” 中会有很多数学函数
- 例如:RandomPointInBoundingBox:随机点在边界框
public: // Called every framevirtual void Tick(float DeltaTime) override;//获取随机位置UFUNCTION(BlueprintCallable, Category = "Spawn Volume")FVector GetSpawnRandomLocation();UFUNCTION(BlueprintCallable, Category = "Spawn Volume")TSubclassOf<AActor> GetSpawnClass();
};
FVector ASpawnVolume::GetSpawnRandomLocation()
{FVector OriginPoint = SpawnBox->GetComponentLocation();FVector Extent = SpawnBox->GetScaledBoxExtent();return UKismetMathLibrary::RandomPointInBoundingBox(OriginPoint,Extent);
}TSubclassOf<AActor> ASpawnVolume::GetSpawnClass()
{if (SpawnClass.Num() > 0){int index = FMath::RandRange(0, SpawnClass.Num() - 1);return SpawnClass[index];}else{return nullptr;}
}
随机生成区域与蓝图本地事件机制
- BlueprintPure参数:可以把函数变成纯净函数没有执行线
- BlueprintNativeEvent参数一般要与BlueprintCallable一起使用,
在蓝图中声明的本地事件使用BlueprintNativeEvent关键词进行标记。它告诉Unreal Engine系统该事件可以在C++中进行实现,并且可以在蓝图中被重写或使用。一旦在蓝图中声明了本地事件,就可以在C++中编写实现该事件的代码。通过继承蓝图类的C++类,可以对该本地事件进行重写或添加额外的逻辑。这样,当在蓝图中调用该本地事件时,将执行C++中实现的代码逻辑。总之,BlueprintNativeEvent关键词允许在Unreal Engine蓝图中声明本地事件,并通过C++进行实现和扩展。这样的设计模式提供了蓝图和C++之间的灵活交互,允许开发人员在保持蓝图的简洁性和可视化优势的同时,利用C++的强大功能来实现高级逻辑和性能优化 - 在C++中实现一个蓝图本地事件时,通常需要在函数名后添加_Implementation作为后缀。例如,如果在蓝图中声明了一个本地事件函数MyEvent,那么在C++中实现它的函数名将是MyEvent_Implementation。
这是因为在Unreal Engine中,蓝图本地事件的实现通常是通过虚函数重写机制来完成的。当蓝图中调用本地事件时,底层引擎会查找与事件函数同名的_Implementation函数,然后执行该函数中的代码逻辑。使用_Implementation作为后缀是一种约定,用于将原始的虚函数和其实现函数进行区分。这样做可以保持函数名的一致性,并且使代码更易于理解和维护。另外,_Implementation函数是在C++类中实现蓝图本地事件的默认方法。你也可以在自定义C++类中以其他的名字实现蓝图本地事件,只需在蓝图中指定相应的函数即可。
总结起来,为了实现蓝图本地事件函数,需要在函数名后添加_Implementation作为后缀。这是为了区分虚函数和其实现函数,并保持代码的一致性和清晰度 GetWorld()->SpawnActor<AActor>(SpawnClasses, SpawnLocation, FRotator(0.0f)):生成Actor在世界中- SpawnActor:函数源码
/** Templated version of SpawnActor that allows you to specify a class type via the template type */template< class T >T* SpawnActor( const FActorSpawnParameters& SpawnParameters = FActorSpawnParameters() ){return CastChecked<T>(SpawnActor(T::StaticClass(), NULL, NULL, SpawnParameters),ECastCheckedType::NullAllowed);}/** Templated version of SpawnActor that allows you to specify location and rotation in addition to class type via the template type */template< class T >T* SpawnActor( FVector const& Location, FRotator const& Rotation, const FActorSpawnParameters& SpawnParameters = FActorSpawnParameters() ){return CastChecked<T>(SpawnActor(T::StaticClass(), &Location, &Rotation, SpawnParameters),ECastCheckedType::NullAllowed);}/** Templated version of SpawnActor that allows you to specify the class type via parameter while the return type is a parent class of that type */template< class T >T* SpawnActor( UClass* Class, const FActorSpawnParameters& SpawnParameters = FActorSpawnParameters() ){return CastChecked<T>(SpawnActor(Class, NULL, NULL, SpawnParameters),ECastCheckedType::NullAllowed);}/** * Templated version of SpawnActor that allows you to specify the rotation and location in addition* class type via parameter while the return type is a parent class of that type */template< class T >T* SpawnActor( UClass* Class, FVector const& Location, FRotator const& Rotation, const FActorSpawnParameters& SpawnParameters = FActorSpawnParameters() ){return CastChecked<T>(SpawnActor(Class, &Location, &Rotation, SpawnParameters),ECastCheckedType::NullAllowed);}/** * Templated version of SpawnActor that allows you to specify whole Transform* class type via parameter while the return type is a parent class of that type */template< class T >T* SpawnActor(UClass* Class, FTransform const& Transform,const FActorSpawnParameters& SpawnParameters = FActorSpawnParameters()){return CastChecked<T>(SpawnActor(Class, &Transform, SpawnParameters), ECastCheckedType::NullAllowed);}
SpawnVolume.h
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SpawnVolume.generated.h"UCLASS()
class UEGAME_API ASpawnVolume : public AActor
{GENERATED_BODY()public: // Sets default values for this actor's propertiesASpawnVolume();//触发器UPROPERTY(VisibleAnywhere, BlueprintReadOnly)class UBoxComponent* SpawnBox;//模版类,用来添加AActor的子类UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Spawn Volume")TArray<TSubclassOf<AActor>> SpawnClass;protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public: // Called every framevirtual void Tick(float DeltaTime) override;//获取随机位置UFUNCTION(BlueprintPure, Category = "Spawn Volume")FVector GetSpawnRandomLocation();UFUNCTION(BlueprintPure, Category = "Spawn Volume")TSubclassOf<AActor> GetSpawnClass();//蓝图本地事件机制UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Spawn Volue")void SpawnActor(UClass* SpawnClasses, FVector SpawnLocation);
};
SpawnVolume.cpp
// Fill out your copyright notice in the Description page of Project Settings.#include "SpawnVolume.h"
#include "Components/BoxComponent.h"
#include "Kismet/KismetMathLibrary.h"
// Sets default values
ASpawnVolume::ASpawnVolume()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;SpawnBox = CreateDefaultSubobject<UBoxComponent>(TEXT("SpawnBox"));RootComponent = SpawnBox;}// Called when the game starts or when spawned
void ASpawnVolume::BeginPlay()
{Super::BeginPlay();}// Called every frame
void ASpawnVolume::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}FVector ASpawnVolume::GetSpawnRandomLocation()
{FVector OriginPoint = SpawnBox->GetComponentLocation();FVector Extent = SpawnBox->GetScaledBoxExtent();return UKismetMathLibrary::RandomPointInBoundingBox(OriginPoint,Extent);
}TSubclassOf<AActor> ASpawnVolume::GetSpawnClass()
{if (SpawnClass.Num() > 0){int index = FMath::RandRange(0, SpawnClass.Num() - 1);return SpawnClass[index];}else{return 0;}
}
//生成Actor
void ASpawnVolume::SpawnActor_Implementation(UClass* SpawnClasses, FVector SpawnLocation)
{GetWorld()->SpawnActor<AActor>(SpawnClasses, SpawnLocation, FRotator(0.0f));
}
- 蓝图中去调用写好的这个机制

- 运行结果

Actor创建移动浮空平台
创建移动平台与EditWidget工具
- 创建一个Actor类,这个Actor需要一个静态网格,两个变量(一个表示起点一个表示终点)
- meta = (EditWidget = “true”):这是一个可选的元标记(Metadata),用于添加额外的属性信息。在这种情况下,MakeEditWidget 被设置为 “true”,这表示该属性可以在编辑器中作为一个小部件进行编辑。这通常用于自定义编辑器小部件以提供更直观的属性编辑体验。
public: // Sets default values for this actor's propertiesAFloatingPlatform();UPROPERTY(VisibleAnywhere,BlueprintReadOnly)class UStaticMeshComponent* PlatformMesh;UPROPERTY(VisibleAnywhere, Category = "Floating Platform")FVector StartPoint{};UPROPERTY(EditAnywhere, Category = "Floating Platform", meta = (MakeEditWidget = "true"))FVector EndPoint{};
- 运行结果

使用VInterpTo进行插值
- 新建一个变量PlatformSpeed用来设置上升速度
public: // Sets default values for this actor's propertiesAFloatingPlatform();UPROPERTY(VisibleAnywhere,BlueprintReadOnly)class UStaticMeshComponent* PlatformMesh;UPROPERTY(VisibleAnywhere, Category = "Floating Platform")FVector StartPoint{};UPROPERTY(EditAnywhere, Category = "Floating Platform", meta = (MakeEditWidget = "true"))FVector EndPoint{};UPROPERTY(EditAnywhere, Category = "Floating Platform")float PlatformSpeed;
- 使用VInterpTo进行移动
- VInterpTo 源码
CORE_API FVector FMath::VInterpTo( const FVector& Current, const FVector& Target, float DeltaTime, float InterpSpeed )
{// If no interp speed, jump to target valueif( InterpSpeed <= 0.f ){return Target;}// Distance to reachconst FVector Dist = Target - Current;// If distance is too small, just set the desired locationif( Dist.SizeSquared() < KINDA_SMALL_NUMBER ){return Target;}// Delta Move, Clamp so we do not over shoot.const FVector DeltaMove = Dist * FMath::Clamp<float>(DeltaTime * InterpSpeed, 0.f, 1.f);return Current + DeltaMove;
}
- VInterpConstantTo:匀速运动源码
CORE_API FVector FMath::VInterpConstantTo(const FVector Current, const FVector& Target, float DeltaTime, float InterpSpeed)
{const FVector Delta = Target - Current;const float DeltaM = Delta.Size();const float MaxStep = InterpSpeed * DeltaTime;if( DeltaM > MaxStep ){if( MaxStep > 0.f ){const FVector DeltaN = Delta / DeltaM;return Current + DeltaN * MaxStep;}else{return Current;}}return Target;
}
- FloatingPlatform.cpp
// Fill out your copyright notice in the Description page of Project Settings.#include "FloatingPlatform.h"
#include "Components/StaticMeshComponent.h"
// Sets default values
AFloatingPlatform::AFloatingPlatform()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;PlatformMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Platform"));RootComponent = PlatformMesh;PlatformSpeed = 2.f;
}// Called when the game starts or when spawned
void AFloatingPlatform::BeginPlay()
{Super::BeginPlay();//获取Actor的世界位置StartPoint = GetActorLocation();EndPoint += StartPoint;
}// Called every frame
void AFloatingPlatform::Tick(float DeltaTime)
{Super::Tick(DeltaTime);FVector CurrentLocation = GetActorLocation();FVector NewLocation = FMath::VInterpTo(CurrentLocation, EndPoint, DeltaTime, PlatformSpeed);SetActorLocation(NewLocation);//移动到新位置
}
使用定时器进行平台来回移动
- 新建一个bool变量bInterping用来判断是否要开启定时器,新建一个DelayTime用来规定延时时间几秒后开启定时器,新键一个用来记录当前位置的变量Distance
- 思路:bInterping默认为true,Distance获取到移动到目标点的位置,在移动过程中,新建一个NewDistace获取当前世界位置减去开始位置的值,判断Distance要是减去NewDistance的值大于等于一个很小的值,就说明到最终位置了,此时的bInterping为false了,该开启定时器返回起点,2秒后定时器中函数表达式bInterping为真,互换起点与终点位置,又进行新一轮平台移动
FloatingPlatform.h
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FloatingPlatform.generated.h"UCLASS()
class UEGAME_API AFloatingPlatform : public AActor
{GENERATED_BODY()public: // Sets default values for this actor's propertiesAFloatingPlatform();UPROPERTY(VisibleAnywhere,BlueprintReadOnly)class UStaticMeshComponent* PlatformMesh;UPROPERTY(VisibleAnywhere, Category = "Floating Platform")FVector StartPoint{};UPROPERTY(EditAnywhere, Category = "Floating Platform", meta = (MakeEditWidget = "true"))FVector EndPoint{};UPROPERTY(EditAnywhere, Category = "Floating Platform")float PlatformSpeed;UPROPERTY(EditAnywhere, Category = "Floating Platform")float DelayTime;FTimerHandle InterpTimerHandle;bool bInterping;float Distance;
protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public: // Called every framevirtual void Tick(float DeltaTime) override;};
FloatingPlatform.cpp
// Fill out your copyright notice in the Description page of Project Settings.#include "FloatingPlatform.h"
#include "Components/StaticMeshComponent.h"
#include "TimerManager.h"
// Sets default values
AFloatingPlatform::AFloatingPlatform()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;PlatformMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("PlatformMesh"));RootComponent = PlatformMesh;PlatformSpeed = 200.f;DelayTime = 2.0f;bInterping = true;
}// Called when the game starts or when spawned
void AFloatingPlatform::BeginPlay()
{Super::BeginPlay();//获取Actor的世界位置StartPoint = GetActorLocation();Distance = EndPoint.Size();EndPoint += StartPoint;}// Called every frame
void AFloatingPlatform::Tick(float DeltaTime)
{Super::Tick(DeltaTime);if (bInterping){FVector CurrentLocation = GetActorLocation();FVector NewLocation = FMath::VInterpConstantTo(CurrentLocation, EndPoint, DeltaTime, PlatformSpeed);SetActorLocation(NewLocation);//移动到新位置float NewDistance = (GetActorLocation() - StartPoint).Size();if (Distance - NewDistance <= 0.5f){bInterping = !bInterping;//Lambda表达式auto ToggleInterpState = [this](){bInterping = !bInterping;};//开启定时器GetWorldTimerManager().SetTimer(InterpTimerHandle, FTimerDelegate::CreateLambda(ToggleInterpState), DelayTime, false);//交换起点与终点FVector temp = StartPoint;StartPoint = EndPoint;EndPoint = temp;}}}
- 运行结果

相关文章:
虚幻C++基础 day3
常见的游戏机制 Actor机关门 创建一个Actor类,添加两个静态网格与一个触发器 UBoxComponentUStaticMeshComponent 头文件: #include “Components/BoxComponent.h”#include “Components/StaticMeshComponent.h” TriggerDoor.h // Fill out your …...
第26期 | GPTSecurity周报
GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区,集成了生成预训练Transformer(GPT)、人工智能生成内容(AIGC)以及大型语言模型(LLM)等安全领域应用的知识。在这里,您可以…...
(动手学习深度学习)第7章 稠密连接网络---DenseNet
目录 DenseNetDenseNet的优点:DenseNet的改进思路总结 DenseNet代码实现 DenseNet DenseNet的优点: 省参数。在 ImageNet 分类数据集上达到同样的准确率,DenseNet 所需的参数量不到 ResNet 的一半。对于工业界而言,小模型可以显著…...
UART编程(寄存器)
1. 串口编程步骤 1.1 看原理图确定引脚 有很多串口,使用哪一个?看原理图确定 1.2 配置引脚为UART功能 至少用到发送、接收引脚:txd、rxd 需要把这些引脚配置为UART功能,并使能UART模块 1.3 设置串口参数 有哪些参数…...
事务码增删查改表数据
常用事务码 SE11 SE14 SE16 SE16N SM30 SE11:查看数据库表/修改表中字段数量_类型/查看表中数据/设置表为可维护或不可维护 SE14:查看数据库表的创建日期创建用户名/查看表中字段/删除表中全部数据(只能全部删) SE16:查看数据库表/对可维护数据库表进行数据维护/SE16通过调试…...
vue开发环境搭建部署(mac版)
前言 目前后端工作越来越少了,年底了,为了先过验收。项目负责人、产品、需求制定的方案就是先做假页面,所以前端的活多点。 其实现在不喜欢搞前端,原因很多,但是感觉现在似乎流行的码林绝学又是九九归一的瓶颈期…...
Java【算法 05】通过时间获取8位验证码(每两个小时生成一个)源码分享
通过时间获取验证码 1.需求2.代码实现2.1 依赖2.2 时间参数处理方法2.3 截取验证码方法2.4 验证方法 3.总结 1.需求 要求是很简单的,每个验证码的有效时间是2小时,这个并不是收到验证码开始计时的,而是每个两小时的时间段使用的是相同的验证…...
微服务 Spring Cloud 5,一图说透Spring Cloud微服务架构
目录 一、域名系统DNS二、LVS(Linux Virtual Server),Linux虚拟服务器三、CDN静态资源四、Nginx反向代理服务器1、Nginx的主要作用体现在以下几个方面:2、Nginx静态资源服务和CDN静态资源服务,如何选择? 五、Gateway网…...
conda清华源安装cuda12.1的pytorch
使用pytorch官方提供的conda command奇慢无比,根本装不下来(科学的情况下也这样) 配置一下清华源使用清华源装就好了 清华源:https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/ 配置方法:conda config --…...
安徽首届道医传承十八绝技发布会在合肥成功举办
近日,在安徽合肥举行了首届道医传承十八绝技发布会,本次会议由安徽渡罗门生物科技有限公司、北京道武易医文化传播有限公司、楼观台道医文化研究院联合举办。现场吸引了来自全国各地民族医学领域的专家学者参与讨论与交流。本次会议旨在促进道医的交流与…...
一款功能强大的web目录扫描器专业版
dirpro 简介 dirpro 是一款由 python 编写的目录扫描器,操作简单,功能强大,高度自动化。 自动根据返回状态码和返回长度,对扫描结果进行二次整理和判断,准确性非常高。 已实现功能 可自定义扫描线程 导入url文件进…...
【Linux网络】网卡配置与修改主机名,做好基础系统配置
目录 一、网络配置命令 1、查看网卡信息ifconfig Linux永久修改ip地址 2、主机名修改 ①hostname 临时修改主机名 ②永久修改主机名 第一种,使用命令修改 第二种:修改配置文件 3、路由信息 再来拓展一下,永久修改路由表信息 4、检查…...
三大基础排序 -选择排序、冒泡排序、插入排序
排序算法 文章目录 冒泡排序算法步骤动图代码优化总结 选择排序算法步骤动图代码总结 插入排序算法步骤动图代码总结 排序算法,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。一般默认排序是按照由小到大即…...
el-form添加自定义校验规则校验el-input只能输入数字
0 效果 1 代码 {1,5}是用来限制小数点后几位的 addFormRules: {investAmount: [{ validator: checkInvestAmount, trigger: blur }], }, const checkInvestAmount (rule, value, callback) > {if (value ! && value ! null && value ! undefined) {if (/…...
ios 开发问题小集 [持续更新]
文章目录 一、如何给列表上的UITableViewCell添加手势二、获取NSIndexPath的方式2.1 根据row, section 来创建2.2 根据point 的位置来找到 indexPath三、tableView在Grouped样式下,设置表头表尾空白一、如何给列表上的UITableViewCell添加手势 给cell添加手势,大家都会这么做…...
idea Plugins 搜索不到插件
Settings — System Settings — HTTP Proxy,打开HTTP Proxy 页面,设置自动发现代理: 勾选Atuto-detect proxy settings,勾选Automatic proxy configuration URL,输入: https://plugins.jetbrains.com/id…...
三相电机的某些实测特性曲线
三相电机参数: 0.75KW,额定电流是2A,功率因数0.71,效率78.9%。制式S1. 1.负载不变时的线电压与线电流的关系 1.1相关数据与python代码: 这里记录了一系列的实验: 第一组实验:近乎空载…...
Essential C++ 面向对象4.1 ~ 5.4
个人认为,结合网上对《Essential c》的评论,它不适合初学者: (1)过于精炼,很多内容不会细讲 (2)中文版翻译较生硬,逻辑不够连贯清晰 (3)课后作业有…...
数组【数据结构与算法】
什么是线性表?什么是非线性表?什么是数组?数组如何实现根据下标随机访问数组元素?为什么数组从下标0开始,不从下标1开始? 什么是线性表? 数据结构元素只有前后关系。 线性表包括:数…...
Python克隆单个网页
网上所有代码都无法完全克隆单个网页,不是Css,Js下载不下来就是下载下来也不能正常显示,只能自己写了,记得点赞~ 效果如图: 源码与所需的依赖: pip install requests pip install requests beautifulsoup4…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
