一. 效果与资源准备
1.1 游戏演示效果
1.2 游戏资产素材与源码
1.3 前期准备
- 创建无初学者内容的空项目
- 将素材文件拷贝到项目 Content 文件夹下
- 搭建场景(用 3D 场景模拟 2D 游戏效果)
二. 创建角色类与全局相机
2.1 创建角色类
- 创建C++类(Character),重命名 Cake(Public)
- 创建继承自 Cake 的蓝图(实例化),重命名 BP_Cake,并存放在 Blueprints 文件夹下
- 设置 BP_Cake 模型资产,并调整胶囊体覆盖模型
- 创建 BP_GameModeBase 游戏模式(GameModeBase),并和 BP_Cake 一起挂载到项目设置,那么在场景中放置玩家出生点 Player Start 后,运行时会自动生成 BP_Cake 的玩家出生点位置
2.2 创建全局相机
- 创建C++类(Actor),重命名 Camera(Public)
- 创建继承自 Camera 的蓝图(实例化),重命名 BP_Camera,并存放在 Blueprints 文件夹下
- 指定默认相机
- 调整相机正交模式
三. 移动逻辑
3.1 角色水平方向跟随鼠标移动
- 获取 PlayerController,运行时显示鼠标
- 角色随鼠标移动
- 防止角色出画,添加阻挡体积
- 运行效果:
3.2 角色垂直方向跳跃
- 角色垂直方向跳跃
- 绑定操作映射
- 运行效果:
3.4 设置角色速度
- 设置角色在空中/落地 2种状态下的不同速度
- 设置角色 BP_Cake 蓝图物理细节参数
3.4 全局相机垂直跟随
- 相机左右并不移动,只需调整 Z 轴跟随
- 设置背景板和阻挡体积为可移动,随摄像机移动
- 运行效果:
四. 创建云朵类
4.1 创建云朵类
- 创建C++类(Actor),重命名 Cloud(Public)
- 创建继承自 Cloud 的蓝图(实例化),重命名 BP_Cloud,并存放在 Blueprints 文件夹下
- 添加盒体检测组件和云朵组件
4.2 随机云朵贴图生成
- 通过修改材质中的,随机生成云朵显示
- 设置云朵的显示,并添加材质数组
- 运行效果(拖放多个 BP_Cloud 到场景中运行测试):
- 调整修改云朵的大小
4.3 角色触碰云朵则触发弹跳
- 重写碰撞函数,检测到角色则调用弹跳函数
- 运行效果(小球触碰到云朵就起飞):
4.4 云朵随机下雨
- 添加云朵雨组件并绑定,随机显示云朵雨
- 设置云朵雨的位置,并添加材质
- 运行效果(随机生成云朵雨):
五. 云朵生成器
5.1 创建云朵生成器
- 创建C++类(Actor),重命名 SpawnCloud(Public)
- 创建继承自 SpawnCloud 的蓝图(实例化),重命名 BP_SpawnCloud,存放在 Blueprints 文件夹下
- 云朵生成器的原理:在高处设置一块云朵生成区 SpawnArea,低处设置一块碰撞检测区 TriggerArea,当角色跳跃碰撞到检测区 TriggerArea,则整体上移,并在生成区 SpawnArea 随机位置生成云朵
5.2 随机位置生成云朵
- 添加云朵生成区域组件和检测生成区域组件
- 随机位置生成云朵
5.3 碰撞检测与初始化上升
- 检测是否与角色产生碰撞
- 云朵生成器的初始化与上升
- 在 BP_SpawnCloud 中调整参数
六. 计分系统与云朵销毁
6.1 计分系统
- 在角色中添加分数和计分方法
- 在云朵中添加分数文本,并显示分数
- 调整分数文本的字体位置大小
6.2 TimeLine 云朵销毁
- 结合蓝图中 Timeline 实现云朵淡入淡出效果
- 销毁相机视角外的多余云朵
- 在场景中调整销毁碰撞检测区域的位置
- 运行效果(销毁时显示计数并变化淡出,落下区域无云朵):
七. 游戏结束与重开
7.1 游戏结束的判定
- 结合蓝图中 Timeline (计数 2s )判断角色是否持续下落,如果持续下落则直接降落到地面
- 游戏结束的判定
7.2 游戏重开按钮
- 创建 UMG 蓝图,直接设计游戏重开按钮 UI(不建议在C++里面用代码创建UI按钮,是一件非常费力不讨好的事情)
- 设置 UI 动画
- 结合蓝图,在游戏结束后显示游戏重开按钮
7.3 点击事件游戏重开
- 添加按钮点击事件
- 重开则重新生成云朵
- 点击重开后,移除UI,调用 C++ 中 GameReset 函数
八. 游戏音乐
8.1 背景音乐
- 将音乐文件拖入场景,设置循环播放
8.2 角色接触云朵音乐
- 按云朵按位置播放音乐
- 设置音乐
8.3 云朵雨音乐
- 添加云朵雨的声音组件,并播放
- 创建雨声音频的 Cue 文件并打开,设置雨声衰减
- 在蓝图中设置云朵雨的音效
附录:C++文件提要
1. Cake.h
1 // Fill out your copyright notice in the Description page of Project Settings. 2 3 #pragma once 4 5 #include "CoreMinimal.h" 6 #include "GameFramework/Character.h" 7 #include "Cake.generated.h" 8 9 UCLASS() 10 class PROJECT_UPUPCAKE_API ACake : public ACharacter 11 { 12 GENERATED_BODY() 13 14 public: 15 // Sets default values for this character's properties 16 ACake(); 17 18 protected: 19 // Called when the game starts or when spawned 20 virtual void BeginPlay() override; 21 22 //声明一个玩家控制器 23 APlayerController* PlayerController; 24 25 //角色在空中的速度 26 UPROPERTY(EditAnywhere,Category="Speed") 27 float AirSpeed; 28 29 //角色落地的速度 30 UPROPERTY(EditAnywhere,Category="Speed") 31 float GroundSpeed; 32 33 //计分 34 int Score; 35 36 //判断是否死亡 37 bool bDeath; 38 39 //判断游戏是否开始 40 bool bGamestart; 41 42 public: 43 // Called every frame 44 virtual void Tick(float DeltaTime) override; 45 46 // Called to bind functionality to input 47 virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; 48 49 //声明角色跟随鼠标移动的函数 50 void FollowMouseCursorMoving(); 51 52 //声明跳跃,游戏启动时跳跃 53 void BeginJump(); 54 55 //声明跳跃,碰到云彩时跳跃 56 void Jump(); 57 58 //判断角色所在的场景,设置速度 59 void SetSpeed(); 60 61 //加分 62 void IncreaseScore(); 63 64 //获取分数 65 int GetScore() const; 66 67 //判断角色是否持续下落 68 void IsFalling(); 69 70 //刷新时间轴 71 UFUNCTION(BlueprintImplementableEvent) 72 void UpdateTimer(); 73 74 //重置时间轴 75 UFUNCTION(BlueprintImplementableEvent) 76 void ResetTimer(); 77 78 //游戏结束 79 UFUNCTION(BlueprintCallable) 80 void GameOver(); 81 82 //游戏重开 83 UFUNCTION(BlueprintCallable) 84 void GameReset(); 85 86 //显示重开按钮 87 UFUNCTION(BlueprintImplementableEvent) 88 void ResetUI(); 89 };
2. Cake.cpp
1 // Fill out your copyright notice in the Description page of Project Settings. 2 3 #include "Cake.h" 4 #include "GameFramework/CharacterMovementComponent.h" //判断角色是否运动 5 6 // Sets default values 7 ACake::ACake() 8 { 9 // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. 10 PrimaryActorTick.bCanEverTick = true; 11 12 //速度初始化 13 AirSpeed = 3500.0f; 14 GroundSpeed = 300.0f; 15 16 //分数初始化 17 Score = 0; 18 19 //判断是否死亡(初始化) 20 bDeath = false; 21 //判断游戏是否开始(初始化) 22 bGamestart = false; 23 } 24 25 // Called when the game starts or when spawned 26 void ACake::BeginPlay() 27 { 28 Super::BeginPlay(); 29 30 //获取 PlayerController(因为继承自 Character,可以直接 GetController()获取) 31 PlayerController = Cast<APlayerController>(GetController()); 32 33 //获取鼠标显示 34 PlayerController->bShowMouseCursor = true; 35 36 //调用游戏重开 37 GameReset(); 38 } 39 40 // Called every frame 41 void ACake::Tick(float DeltaTime) 42 { 43 Super::Tick(DeltaTime); 44 45 if(!bDeath) 46 { 47 FollowMouseCursorMoving(); //每帧判断角色朝鼠标方向移动 48 49 SetSpeed(); //每帧判断角色所在的场景,设置速度 50 51 IsFalling(); //每帧判断角色是否持续下落 52 } 53 } 54 55 // Called to bind functionality to input 56 void ACake::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) 57 { 58 Super::SetupPlayerInputComponent(PlayerInputComponent); 59 60 //跳跃绑定 61 PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACake::BeginJump); 62 } 63 64 void ACake::FollowMouseCursorMoving() 65 { 66 //获取鼠标在世界坐标下的位置(方向暂用不到) 67 FVector MouseCursorLocation; 68 FVector MouseCursorDirection; 69 PlayerController->DeprojectMousePositionToWorld(MouseCursorLocation, MouseCursorDirection); 70 71 //角色朝鼠标方向移动 72 //获取 Y方向(左右方向)的偏移:鼠标位置-小球位置,用 Clamp()函数限定范围为 -1到 1 73 float YDirection = FMath::Clamp(MouseCursorLocation.Y - GetActorLocation().Y, -1.0f ,1.0f); 74 FVector Direction = FVector(0,YDirection,0); //转换为向量 75 AddMovementInput(Direction); 76 77 } 78 79 void ACake::BeginJump() 80 { 81 if(!bGamestart && GetActorLocation().Z != 0) 82 { 83 bGamestart = true; //游戏开始 84 Jump(); 85 } 86 } 87 88 void ACake::Jump() 89 { 90 //LaunchCharacter(发射方向,false:XY方向,true:Z方向),弹跳函数只对角色有效 91 //false/true:是否替换原发射速度(true一直保持 1500) 92 LaunchCharacter(FVector(0,0,1500),false, true); 93 } 94 95 void ACake::SetSpeed() 96 { 97 //判断角色是否下落 98 if(GetCharacterMovement()->IsFalling()) 99 { 100 GetCharacterMovement()->MaxWalkSpeed = AirSpeed; //在空中 101 } 102 else 103 { 104 if(bGamestart) 105 { 106 GameOver(); 107 } 108 GetCharacterMovement()->MaxWalkSpeed = GroundSpeed; //在地面 109 } 110 } 111 112 void ACake::IncreaseScore() 113 { 114 Score++; 115 } 116 117 int ACake::GetScore() const 118 { 119 return Score; 120 } 121 122 void ACake::IsFalling() 123 { 124 //如果 Z方向小于0,则表示准备开始下落了 125 if(GetCharacterMovement()->Velocity.Z < 0) 126 { 127 //持续性下落,刷新时间轴 128 UpdateTimer(); 129 } 130 else 131 { 132 //短暂性下落,重置时间轴 133 ResetTimer(); 134 135 } 136 } 137 138 void ACake::GameOver() 139 { 140 bDeath = true; 141 SetActorRotation(FRotator::ZeroRotator); //旋转归零 142 EnableInput(PlayerController); //启用输入 143 144 //显示重开按钮 145 UE_LOG(LogTemp,Warning, TEXT("GameOver")); 146 147 ResetUI(); 148 149 } 150 151 void ACake::GameReset() 152 { 153 Score = 0; 154 bDeath = false; 155 bGamestart = false; 156 }
3.Camera.h
1 // Fill out your copyright notice in the Description page of Project Settings. 2 3 #pragma once 4 5 #include "CoreMinimal.h" 6 #include "Camera/CameraComponent.h" 7 #include "GameFramework/Actor.h" 8 #include "Cake.h" //角色 9 #include "Components/BoxComponent.h" //盒体检测 10 #include "Camera.generated.h" 11 12 UCLASS() 13 class PROJECT_UPUPCAKE_API ACamera : public AActor 14 { 15 GENERATED_BODY() 16 17 public: 18 // Sets default values for this actor's properties 19 ACamera(); 20 21 protected: 22 // Called when the game starts or when spawned 23 virtual void BeginPlay() override; 24 25 //声明一个相机组件 26 UPROPERTY(VisibleAnywhere) 27 UCameraComponent* CameraComponent; 28 29 //声明一个玩家控制器 30 APlayerController* PlayerController; 31 32 //声明角色 33 ACake* Cake; 34 35 //销毁相机视角外的多余云朵 36 UPROPERTY(VisibleAnywhere, Category = "Component") 37 UBoxComponent* DestroyArea; 38 39 public: 40 // Called every frame 41 virtual void Tick(float DeltaTime) override; 42 43 //全局相机垂直跟随 44 void CameraMoving(); 45 46 //检测销毁区是否与多余云朵产生碰撞 47 virtual void NotifyActorBeginOverlap(AActor* OtherActor) override; //重写碰撞函数 48 };
4. Camera.cpp
1 // Fill out your copyright notice in the Description page of Project Settings. 2 3 #include "Camera.h" 4 #include "Camera/CameraComponent.h" //相机组件 5 #include "Kismet/GameplayStatics.h" //玩家控制器 6 #include "Cloud.h" //销毁相机视角外的多余云朵 7 8 // Sets default values 9 ACamera::ACamera() 10 { 11 // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. 12 PrimaryActorTick.bCanEverTick = true; 13 14 //定义一个相机组件 15 CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent")); 16 //将相机组件设置为默认根组件 17 CameraComponent->SetupAttachment(RootComponent); 18 19 //销毁相机视角外的多余云朵 20 DestroyArea = CreateDefaultSubobject<UBoxComponent>(TEXT("DestroyArea")); 21 //绑定到根组件 22 DestroyArea->SetupAttachment(RootComponent); 23 24 } 25 26 // Called when the game starts or when spawned 27 void ACamera::BeginPlay() 28 { 29 Super::BeginPlay(); 30 31 //获取玩家控制器 32 PlayerController = UGameplayStatics::GetPlayerController(this, 0); 33 //切换视角(立刻对齐) 34 PlayerController->SetViewTargetWithBlend(this, 0); 35 36 //获取角色 37 Cake = Cast<ACake>(UGameplayStatics::GetPlayerPawn(this,0)); 38 39 } 40 41 // Called every frame 42 void ACamera::Tick(float DeltaTime) 43 { 44 Super::Tick(DeltaTime); 45 46 CameraMoving(); //每帧调用全局相机垂直跟随 47 } 48 49 void ACamera::CameraMoving() 50 { 51 //(相机的 X,相机的 Y,角色的 Z)组成跟随坐标 52 FVector TargetLoaction = FVector(GetActorLocation().X, GetActorLocation().Y, Cake->GetActorLocation().Z); 53 //设置相机当前位置 54 SetActorLocation(TargetLoaction); 55 } 56 57 void ACamera::NotifyActorBeginOverlap(AActor* OtherActor) 58 { 59 Super::NotifyActorBeginOverlap(OtherActor); 60 61 //类型转换 62 ACloud* Cloud = Cast<ACloud>(OtherActor); 63 if(Cloud) 64 { 65 //检测到多余云朵则调用销毁 66 Cloud->Destroy(); 67 } 68 }
5. Cloud.h
1 // Fill out your copyright notice in the Description page of Project Settings. 2 3 #pragma once 4 5 #include "CoreMinimal.h" 6 #include "Components/BoxComponent.h" 7 #include "GameFramework/Actor.h" 8 #include "Cake.h" //角色 9 #include "Components/TextRenderComponent.h" //文本 10 #include "Sound/SoundWave.h" //播放音乐 11 #include "Cloud.generated.h" 12 13 UCLASS() 14 class PROJECT_UPUPCAKE_API ACloud : public AActor 15 { 16 GENERATED_BODY() 17 18 public: 19 // Sets default values for this actor's properties 20 ACloud(); 21 22 protected: 23 // Called when the game starts or when spawned 24 virtual void BeginPlay() override; 25 26 //声明盒体检测组件 27 UPROPERTY(VisibleAnywhere, Category = "Collision") 28 UBoxComponent* BoxComponent; 29 30 //声明云朵组件 31 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Show") 32 UStaticMeshComponent* CloudPlane; 33 34 //声明云朵雨组件 35 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Show") 36 UStaticMeshComponent* RainPlane; 37 38 //云朵库 39 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Show") 40 TArray<UTexture*> CloudTextures; 41 42 //动态材质实例 43 UPROPERTY(BlueprintReadOnly, Category = "Show") 44 UMaterialInstanceDynamic* MaterialInstanceDynamic; 45 46 UMaterialInterface* MaterialInterface; 47 48 //分数文本 49 UPROPERTY(EditAnywhere, Category = "Show") 50 UTextRenderComponent* ScoreText; 51 52 //检测是否与角色产生碰撞 53 ACake* Cake; 54 55 //角色接触云朵音乐 56 UPROPERTY(EditAnywhere, Category = "Sound") 57 USoundWave* CloudSound; 58 59 //云朵雨音乐 60 UPROPERTY(VisibleAnywhere, Category = "Sound") 61 UAudioComponent* RainSound; 62 63 public: 64 // Called every frame 65 virtual void Tick(float DeltaTime) override; 66 67 //随机云朵生成 68 void SetRandomCloudTextures(); 69 70 //显示分数 71 void DisplayScore(); 72 73 //检测是否与角色产生碰撞 74 virtual void NotifyActorBeginOverlap(AActor* OtherActor) override; //重写碰撞函数 75 76 //云朵淡出(蓝图实现) 77 UFUNCTION(BlueprintImplementableEvent) 78 void FadeOut(); 79 };
6. Cloud.cpp
1 // Fill out your copyright notice in the Description page of Project Settings. 2 3 #include "Cloud.h" 4 #include "Kismet/GameplayStatics.h" //播放音乐 5 #include "Components/AudioComponent.h" //云朵雨音乐组件 6 7 // Sets default values 8 ACloud::ACloud() 9 { 10 // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. 11 PrimaryActorTick.bCanEverTick = true; 12 13 //定义盒体检测 14 BoxComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxCollision")); 15 //设置为默认根组件 16 RootComponent = BoxComponent; 17 18 //定义云朵 19 CloudPlane = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CloudMesh")); 20 //绑定到根组件(盒体检测) 21 CloudPlane->SetupAttachment(RootComponent); 22 23 //定义云朵雨 24 RainPlane = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("RainMesh")); 25 //绑定到云朵组件 26 RainPlane->SetupAttachment(CloudPlane); 27 28 //分数文本 29 ScoreText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("ScoreText")); 30 //绑定到根组件 31 ScoreText->SetupAttachment(RootComponent); 32 33 //云朵雨音乐 34 RainSound = CreateDefaultSubobject<UAudioComponent>(TEXT("RainSound")); 35 //绑定到云朵组件 36 RainSound->SetupAttachment(CloudPlane); 37 } 38 39 // Called when the game starts or when spawned 40 void ACloud::BeginPlay() 41 { 42 Super::BeginPlay(); 43 44 SetRandomCloudTextures(); //调用随机云朵生成 45 46 //随机显示云朵雨 47 if(FMath::RandRange(0,2)) 48 { 49 RainPlane->SetVisibility(true); 50 51 //播放云朵雨音乐 52 RainSound->Activate(true); 53 } 54 } 55 56 // Called every frame 57 void ACloud::Tick(float DeltaTime) 58 { 59 Super::Tick(DeltaTime); 60 61 } 62 63 void ACloud::SetRandomCloudTextures() 64 { 65 //获取 CloudPlane上的材质 66 MaterialInterface = CloudPlane->GetMaterial(0); 67 68 //通过创建动态材质实例来获取指定材质参数的随机材质 69 MaterialInstanceDynamic = CloudPlane->CreateDynamicMaterialInstance(0,MaterialInterface); 70 71 //随机数 72 int index = FMath::RandRange(0,2); 73 74 if(CloudTextures[index]) 75 { 76 //设置材质参数值(参数节点名Texture,随机云彩库) 77 MaterialInstanceDynamic->SetTextureParameterValue(FName(TEXT("Texture")), CloudTextures[index]); 78 //将材质实例赋给模型 79 CloudPlane->SetMaterial(0, MaterialInstanceDynamic); 80 } 81 } 82 83 void ACloud::NotifyActorBeginOverlap(AActor* OtherActor) 84 { 85 Super::NotifyActorBeginOverlap(OtherActor); 86 87 //类型转换 88 Cake = Cast<ACake>(OtherActor); 89 if(Cake) 90 { 91 //按位置播放音乐 92 UGameplayStatics::PlaySoundAtLocation(this, CloudSound, GetActorLocation()); 93 //检测到角色则调用弹跳 94 Cake->Jump(); 95 //显示分数 96 DisplayScore(); 97 98 //云朵淡出(蓝图实现) 99 FadeOut(); 100 } 101 } 102 103 void ACloud::DisplayScore() 104 { 105 Cake->IncreaseScore(); 106 107 //设置文本(类型转换 int - FString - FText) 108 ScoreText->SetText(FText::FromString(FString::FromInt(Cake->GetScore()))); 109 }
7. SpawnCloud.h
1 // Fill out your copyright notice in the Description page of Project Settings. 2 3 #pragma once 4 5 #include "CoreMinimal.h" 6 #include "Cloud.h" 7 #include "GameFramework/Actor.h" 8 #include "Components/BoxComponent.h" //盒体检测 9 #include "SpawnCloud.generated.h" 10 11 UCLASS() 12 class PROJECT_UPUPCAKE_API ASpawnCloud : public AActor 13 { 14 GENERATED_BODY() 15 16 public: 17 // Sets default values for this actor's properties 18 ASpawnCloud(); 19 20 protected: 21 // Called when the game starts or when spawned 22 virtual void BeginPlay() override; 23 24 //云朵生成区域 25 UPROPERTY(VisibleAnywhere, Category = "Component") 26 UBoxComponent* SpawnArea; 27 28 //根据角色位置,检测云朵是否可以继续生成 29 UPROPERTY(VisibleAnywhere, Category = "Component") 30 UBoxComponent* TriggerArea; 31 32 //场景根组件 33 USceneComponent* DefaultRootComponent; 34 35 //TSubclassOf:限定为 ACloud或其子类 36 UPROPERTY(EditAnywhere, Category = "Cloud") 37 TSubclassOf<ACloud> Cloud; 38 39 //检测是否与角色产生碰撞 40 ACake* Cake; 41 42 //云朵初始化 43 UPROPERTY(EditAnywhere, Category = "Cloud") 44 int32 InitialCloud; 45 46 //云朵生成器每次上升距离 47 UPROPERTY(EditAnywhere, Category = "Cloud") 48 float SpawnSpacing; 49 50 public: 51 // Called every frame 52 virtual void Tick(float DeltaTime) override; 53 54 //随机生成云朵 55 void SpawnCloud(); 56 57 //检测是否与角色产生碰撞 58 virtual void NotifyActorBeginOverlap(AActor* OtherActor) override; //重写碰撞函数 59 60 //重开则重新生成云朵 61 UFUNCTION(BlueprintCallable) 62 void ResetCloud(); 63 64 };
8. SpawnCloud.cpp
1 // Fill out your copyright notice in the Description page of Project Settings. 2 3 #include "SpawnCloud.h" 4 #include "Kismet/KismetMathLibrary.h" //随机生成点 5 #include "Cloud.h" //生成云朵 6 #include "Kismet/GameplayStatics.h" //重开销毁之前的所有云朵 7 8 // Sets default values 9 ASpawnCloud::ASpawnCloud() 10 { 11 // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. 12 PrimaryActorTick.bCanEverTick = true; 13 14 //场景根组件 15 DefaultRootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("DefaultRootComponent")); 16 RootComponent = DefaultRootComponent; 17 18 //云朵生成区域 19 SpawnArea = CreateDefaultSubobject<UBoxComponent>(TEXT("SpawnArea")); 20 //绑定到场景根组件 21 SpawnArea->SetupAttachment(RootComponent); 22 23 //根据角色位置,检测云朵是否可以继续生成 24 TriggerArea = CreateDefaultSubobject<UBoxComponent>(TEXT("TriggerArea")); 25 //绑定到场景根组件 26 TriggerArea->SetupAttachment(RootComponent); 27 28 //云朵初始化 29 InitialCloud = 6; 30 //云朵生成器每次上升距离 31 SpawnSpacing = 300.0f; 32 } 33 34 // Called when the game starts or when spawned 35 void ASpawnCloud::BeginPlay() 36 { 37 Super::BeginPlay(); 38 39 ResetCloud(); 40 } 41 42 // Called every frame 43 void ASpawnCloud::Tick(float DeltaTime) 44 { 45 Super::Tick(DeltaTime); 46 47 } 48 49 void ASpawnCloud::SpawnCloud() 50 { 51 FVector SpawnOrigin = SpawnArea->Bounds.Origin; //生成中心点 52 FVector SpawnExtent = SpawnArea->Bounds.BoxExtent; //生成范围 53 54 //生成的位置 55 //提供圆心和范围,Y轴随机生成点 56 float YLocation = UKismetMathLibrary::RandomPointInBoundingBox(SpawnOrigin, SpawnExtent).Y; 57 FVector SpawnLocation = FVector(SpawnArea->GetComponentLocation().X, YLocation, SpawnArea->GetComponentLocation().Z); 58 59 //生成(生成云朵,生成位置,生成旋转) 60 GetWorld()->SpawnActor<ACloud>(Cloud, SpawnLocation, FRotator::ZeroRotator); 61 62 //云朵生成器上升(0,0,300) 63 AddActorWorldOffset(FVector(0,0,SpawnSpacing)); 64 } 65 66 void ASpawnCloud::NotifyActorBeginOverlap(AActor* OtherActor) 67 { 68 Super::NotifyActorBeginOverlap(OtherActor); 69 70 //类型转换 71 Cake = Cast<ACake>(OtherActor); 72 if(Cake) 73 { 74 //检测到角色则调用随机生成云朵 75 SpawnCloud(); 76 } 77 } 78 79 void ASpawnCloud::ResetCloud() 80 { 81 //云朵初始化 82 InitialCloud = 6; 83 84 //刷新位置为(0,0,0) 85 SetActorLocation(FVector::ZeroVector); 86 87 //重开销毁之前的所有云朵 88 TArray<AActor*>ResetClouds; 89 UGameplayStatics::GetAllActorsOfClass(GetWorld(), ACloud::StaticClass(), ResetClouds); 90 for(AActor* TActor : ResetClouds) 91 { 92 ACloud* FoundClouds = Cast<ACloud>(TActor); //类型转换 93 if(FoundClouds!= nullptr) 94 { 95 FoundClouds->Destroy(); 96 } 97 } 98 99 //云朵初始化随机生成 100 while(InitialCloud > 0) 101 { 102 SpawnCloud(); 103 InitialCloud--; 104 } 105 }
参考资料:
【SiKi学院Unreal视频教程】UE4/5 虚幻4/5初级课程-向上的小松饼_哔哩哔哩_bilibili
标签:云朵,角色,void,C++,Cake,UE,松饼,include,ACake From: https://www.cnblogs.com/ZWJ-zwj/p/17809517.html