上一部分吧 GameMode 都綁定好了,現在把模型和相機放到 PlayerCharacter 上去
先做准備工作
如果我們寫C++文件想要看到實時的效果,需要在 Content 下加個 Blueprint 文件夾,其下再創建個 Temp 文件夾,這個Temp 中保存寫的一些藍圖,這些藍圖在項目完成以后是不需要的。
添加藍圖
由於我們是要一邊寫 PlayerCharacter 一邊看他的效果,所以我們要選擇創建一個繼承自 PlayerCharacter 的藍圖,命名為 PlayerCharacterBP
這樣便可以修改C++代碼的同時動態的看到其實時效果
D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Private\Player\SlAiPlayerCharacter.cpp
1 #include "Player/SlAiPlayerCharacter.h" 2 3 4 // Sets default values 5 ASlAiPlayerCharacter::ASlAiPlayerCharacter() 6 { 7 // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. 8 PrimaryActorTick.bCanEverTick = true; 9 10 /** 11 * 創建 Component(屬性) 12 * CreateDefaultSubobject<T>() 在構造函數中創建使用 13 * NewObject<T> 如果要在其他位置的代碼或者藍圖中創建,可以用 NewObject,用來創建 Uobject 類型 14 */ 15 16 /** 17 * 給默認 Mesh 添加骨骼模型 18 * 19 * Uobject 資源加載 20 * ConstructorHelpers::FObjectFinder<T>只能在構造函數使用 21 * LoadObiect<T>可以在任何地方使用 22 * 23 * 藍圖資源加載 24 * ConstructorHelpers::FClassFinder <T>只能在構造函數使用 25 * LoadClass<T>可以在任何地方加載 26 * 27 * 全局加載資源函數 28 * StaticLoadObject、StaticLoadClass 29 * 應該是早期的LoadObiect<T>和LoadClass<T>的版本 30 */ 31 static ConstructorHelpers::FObjectFinder<USkeletalMesh> StaticMeshThird(TEXT("SkeletalMesh'/Game/AssetsvilleTown/Meshes/Characters/SK_citizen_female_10.SK_citizen_female_10'")); 32 GetMesh()->SetSkeletalMesh(StaticMeshThird.Object); 33 GetMesh()->bOnlyOwnerSee = true; //如果該值為True,則該組件僅在視圖參與者是該組件的所有者時才可見。直接或間接。 34 GetMesh()->bReceivesDecals = false; //是否接收光線反射 35 GetMesh()->SetCollisionObjectType(ECC_Pawn); //在骨架網格上設置碰撞對象類型 36 GetMesh()->SetCollisionEnabled(ECollisionEnabled::NoCollision); //我們的碰撞都會放到根組件的橢圓碰撞,這里設置無碰撞 37 GetMesh()->SetCollisionResponseToChannels(ECR_Ignore); //讓這個Mesh忽略所有的碰撞 38 GetMesh()->SetRelativeLocation(FVector(0.f, 0.f, -95.f)); //設置位置 39 GetMesh()->SetRelativeRotation(FQuat::MakeFromEuler(FVector(0.f, 0.f, -90.f))); //設置旋轉 40 } 41 42 // Called when the game starts or when spawned 43 void ASlAiPlayerCharacter::BeginPlay() 44 { 45 Super::BeginPlay(); 46 } 47 48 // Called every frame 49 void ASlAiPlayerCharacter::Tick(float DeltaTime) 50 { 51 Super::Tick(DeltaTime); 52 } 53 54 // Called to bind functionality to input 55 void ASlAiPlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) 56 { 57 Super::SetupPlayerInputComponent(PlayerInputComponent); 58 }
可以看到第三人稱的模型已經放到了原點,擁有正的朝向和高度,碰撞屬性也都配置好了
下面是第一人稱的配置
d:\ue4 project\ue26.2\courseproject\slaicourse\Source\SlAiCourse\Public\Player\SlAiPlayerCharacter.h
1 #include "CoreMinimal.h" 2 #include "GameFramework/Character.h" 3 #include "SlAiPlayerCharacter.generated.h" 4 5 UCLASS() 6 class SLAICOURSE_API ASlAiPlayerCharacter : public ACharacter 7 { 8 GENERATED_BODY() 9 10 public: 11 // Sets default values for this character's properties 12 ASlAiPlayerCharacter(); 13 14 protected: 15 // Called when the game starts or when spawned 16 virtual void BeginPlay() override; 17 18 public: 19 // Called every frame 20 virtual void Tick(float DeltaTime) override; 21 22 // Called to bind functionality to input 23 virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; 24 25 //第一人稱的骨骼模型,VisibleDefaultsOnly 默認的, 26 UPROPERTY(VisibleDefaultsOnly, Category = "SlAi") 27 USkeletalMeshComponent* MeshFirst; 28 };
D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Private\Player\SlAiPlayerCharacter.cpp
1 #include "Player/SlAiPlayerCharacter.h" 2 3 4 // Sets default values 5 ASlAiPlayerCharacter::ASlAiPlayerCharacter() 6 { 7 // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. 8 PrimaryActorTick.bCanEverTick = true; 9 10 /** 11 * 創建 Component(屬性) 12 * CreateDefaultSubobject<T>() 在構造函數中創建使用 13 * NewObject<T> 如果要在其他位置的代碼或者藍圖中創建,可以用 NewObject,用來創建 Uobject 類型 14 * 15 * 給默認 Mesh 添加骨骼模型 16 * 17 * Uobject 資源加載 18 * ConstructorHelpers::FObjectFinder<T>只能在構造函數使用 19 * LoadObiect<T>可以在任何地方使用 20 * 21 * 藍圖資源加載 22 * ConstructorHelpers::FClassFinder <T>只能在構造函數使用 23 * LoadClass<T>可以在任何地方加載 24 * 25 * 全局加載資源函數 26 * StaticLoadObject、StaticLoadClass 27 * 應該是早期的LoadObiect<T>和LoadClass<T>的版本 28 */ 29 30 //添加第一人稱骨骼模型 31 static ConstructorHelpers::FObjectFinder<USkeletalMesh> StaticMeshFirst(TEXT("SkeletalMesh'/Game/AssetsvilleTown/Meshes/Characters/SK_citizen_female_10.SK_citizen_female_10'")); 32 MeshFirst = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("MeshFirst")); //實例化 33 MeshFirst->SetSkeletalMesh(StaticMeshFirst.Object); //設置骨骼模型 34 MeshFirst->SetupAttachment((USceneComponent*)GetCapsuleComponent()); //將Component添加到碰撞組件下 35 MeshFirst->bOnlyOwnerSee = true; //如果該值為True,則該組件僅在視圖參與者是該組件的所有者時才可見。直接或間接。 36 //MeshFirst->bCastDynamicShadow = false; //是否渲染模型影子(如果你用的是兩個手臂一樣的模型,那就 false 屏蔽掉),默認是顯示 37 MeshFirst->bReceivesDecals = false; //是否接收光線反射 38 //更新頻率衰落 39 MeshFirst->MeshComponentUpdateFlag = EMeshComponentUpdateFlag::OnlyTickMontagesWhenNotRendered; 40 MeshFirst->PrimaryComponentTick.TickGroup = TG_PrePhysics; 41 //設置碰撞屬性 42 MeshFirst->SetCollisionObjectType(ECC_Pawn); //在骨架網格上設置碰撞對象類型 43 MeshFirst->SetCollisionEnabled(ECollisionEnabled::NoCollision); //我們的碰撞都會放到根組件的橢圓碰撞,這里設置無碰撞 44 MeshFirst->SetCollisionResponseToAllChannels(ECR_Ignore); //讓這個Mesh忽略所有的碰撞 45 //設置位移 46 MeshFirst->SetRelativeLocation(FVector(0.f, 0.f, -95.f)); //設置位置 47 MeshFirst->SetRelativeRotation(FQuat::MakeFromEuler(FVector(0.f, 0.f, -90.f))); //設置旋轉 48 49 //添加第三人稱骨骼模型 50 static ConstructorHelpers::FObjectFinder<USkeletalMesh> StaticMeshThird(TEXT("SkeletalMesh'/Game/AssetsvilleTown/Meshes/Characters/SK_citizen_female_10.SK_citizen_female_10'")); 51 GetMesh()->SetSkeletalMesh(StaticMeshThird.Object); 52 GetMesh()->bOnlyOwnerSee = true; 53 GetMesh()->bReceivesDecals = false; 54 GetMesh()->SetCollisionObjectType(ECC_Pawn); 55 GetMesh()->SetCollisionEnabled(ECollisionEnabled::NoCollision); 56 GetMesh()->SetCollisionResponseToAllChannels(ECR_Ignore); 57 GetMesh()->SetRelativeLocation(FVector(0.f, 0.f, -95.f)); 58 GetMesh()->SetRelativeRotation(FQuat::MakeFromEuler(FVector(0.f, 0.f, -90.f))); 59 } 60 61 // Called when the game starts or when spawned 62 void ASlAiPlayerCharacter::BeginPlay() 63 { 64 Super::BeginPlay(); 65 } 66 67 // Called every frame 68 void ASlAiPlayerCharacter::Tick(float DeltaTime) 69 { 70 Super::Tick(DeltaTime); 71 } 72 73 // Called to bind functionality to input 74 void ASlAiPlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) 75 { 76 Super::SetupPlayerInputComponent(PlayerInputComponent); 77 }
添加攝像機
d:\ue4 project\ue26.2\courseproject\slaicourse\Source\SlAiCourse\Public\Player\SlAiPlayerCharacter.h
1 #include "CoreMinimal.h" 2 #include "GameFramework/Character.h" 3 #include "SlAiPlayerCharacter.generated.h" 4 5 UCLASS() 6 class SLAICOURSE_API ASlAiPlayerCharacter : public ACharacter 7 { 8 GENERATED_BODY() 9 10 public: 11 // Sets default values for this character's properties 12 ASlAiPlayerCharacter(); 13 14 // Called every frame 15 virtual void Tick(float DeltaTime) override; 16 17 // Called to bind functionality to input 18 virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; 19 20 public: 21 UPROPERTY(VisibleDefaultsOnly, Category = "SlAi") 22 class USpringArmComponent* CameraBoom; //相當於一個攝像機的搖桿 23 24 UPROPERTY(VisibleDefaultsOnly, Category = "SlAi") 25 class UCameraComponent* ThirdCamera; //第三人稱攝像機組件 26 27 UPROPERTY(VisibleDefaultsOnly, Category = "SlAi") 28 UCameraComponent* FirstCamera; //第一人稱攝像機組件 29 30 protected: 31 // Called when the game starts or when spawned 32 virtual void BeginPlay() override; 33 34 public: 35 //第一人稱的骨骼模型,VisibleDefaultsOnly 默認的, 36 UPROPERTY(VisibleDefaultsOnly, Category = "SlAi") 37 USkeletalMeshComponent* MeshFirst; 38 };
D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Private\Player\SlAiPlayerCharacter.cpp
1 #include "Player/SlAiPlayerCharacter.h" 2 #include "UObject/Object.h" 3 #include "GameFramework/SpringArmComponent.h" 4 #include "Camera/CameraComponent.h" 5 6 7 // Sets default values 8 ASlAiPlayerCharacter::ASlAiPlayerCharacter() 9 { 10 // Set this character 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 * 創建 Component(屬性) 15 * CreateDefaultSubobject<T>() 在構造函數中創建使用 16 * NewObject<T> 如果要在其他位置的代碼或者藍圖中創建,可以用 NewObject,用來創建 Uobject 類型 17 * 18 * 給默認 Mesh 添加骨骼模型 19 * 20 * Uobject 資源加載 21 * ConstructorHelpers::FObjectFinder<T>只能在構造函數使用 22 * LoadObiect<T>可以在任何地方使用 23 * 24 * 藍圖資源加載 25 * ConstructorHelpers::FClassFinder <T>只能在構造函數使用 26 * LoadClass<T>可以在任何地方加載 27 * 28 * 全局加載資源函數 29 * StaticLoadObject、StaticLoadClass 30 * 應該是早期的LoadObiect<T>和LoadClass<T>的版本 31 */ 32 33 //添加第一人稱骨骼模型 34 static ConstructorHelpers::FObjectFinder<USkeletalMesh> StaticMeshFirst(TEXT("SkeletalMesh'/Game/AssetsvilleTown/Meshes/Characters/SK_citizen_female_10.SK_citizen_female_10'")); 35 MeshFirst = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("MeshFirst")); //實例化 36 MeshFirst->SetSkeletalMesh(StaticMeshFirst.Object); //設置骨骼模型 37 MeshFirst->SetupAttachment((USceneComponent*)GetCapsuleComponent()); //將Component添加到碰撞組件下 38 MeshFirst->bOnlyOwnerSee = true; //如果該值為True,則該組件僅在視圖參與者是該組件的所有者時才可見。直接或間接。 39 //MeshFirst->bCastDynamicShadow = false; //是否渲染模型影子(如果你用的是兩個手臂一樣的模型,那就 false 屏蔽掉),默認是顯示 40 MeshFirst->bReceivesDecals = false; //是否接收光線反射 41 //更新頻率衰落 42 MeshFirst->MeshComponentUpdateFlag = EMeshComponentUpdateFlag::OnlyTickMontagesWhenNotRendered; 43 MeshFirst->PrimaryComponentTick.TickGroup = TG_PrePhysics; 44 //設置碰撞屬性 45 MeshFirst->SetCollisionObjectType(ECC_Pawn); //在骨架網格上設置碰撞對象類型 46 MeshFirst->SetCollisionEnabled(ECollisionEnabled::NoCollision); //我們的碰撞都會放到根組件的橢圓碰撞,這里設置無碰撞 47 MeshFirst->SetCollisionResponseToAllChannels(ECR_Ignore); //讓這個Mesh忽略所有的碰撞 48 //設置位移 49 MeshFirst->SetRelativeLocation(FVector(0.f, 0.f, -95.f)); //設置位置 50 MeshFirst->SetRelativeRotation(FQuat::MakeFromEuler(FVector(0.f, 0.f, -90.f))); //設置旋轉 51 52 //添加第三人稱骨骼模型 53 static ConstructorHelpers::FObjectFinder<USkeletalMesh> StaticMeshThird(TEXT("SkeletalMesh'/Game/AssetsvilleTown/Meshes/Characters/SK_citizen_female_10.SK_citizen_female_10'")); 54 GetMesh()->SetSkeletalMesh(StaticMeshThird.Object); 55 GetMesh()->bOnlyOwnerSee = true; 56 GetMesh()->bReceivesDecals = false; 57 GetMesh()->SetCollisionObjectType(ECC_Pawn); 58 GetMesh()->SetCollisionEnabled(ECollisionEnabled::NoCollision); 59 GetMesh()->SetCollisionResponseToAllChannels(ECR_Ignore); 60 GetMesh()->SetRelativeLocation(FVector(0.f, 0.f, -95.f)); 61 GetMesh()->SetRelativeRotation(FQuat::MakeFromEuler(FVector(0.f, 0.f, -90.f))); 62 63 //攝像機手臂 64 CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom")); 65 CameraBoom->SetupAttachment(RootComponent); 66 //設置距離 67 CameraBoom->TargetArmLength = 300.f; 68 //設置偏移 69 CameraBoom->TargetOffset = FVector(0.f, 0.f, 60.f); 70 //綁定 Controller 的旋轉 71 CameraBoom->bUsePawnControlRotation = true; 72 73 //初始化第三人稱攝像機 74 ThirdCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("ThirdCamera")); 75 ThirdCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); 76 //設置 ThirdCamera 不跟隨控制器的旋轉 77 ThirdCamera->bUsePawnControlRotation = false; 78 79 //初始化第一人稱攝像機 80 FirstCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstCamera")); 81 FirstCamera->SetupAttachment((USceneComponent*)GetCapsuleComponent()); 82 //設置跟隨 Controller 的旋轉 83 FirstCamera->bUsePawnControlRotation = true; 84 85 //位置偏移 86 FirstCamera->AddLocalOffset(FVector(0.f, 0.f, 60.f)); 87 } 88 89 // Called when the game starts or when spawned 90 void ASlAiPlayerCharacter::BeginPlay() 91 { 92 Super::BeginPlay(); 93 } 94 95 // Called every frame 96 void ASlAiPlayerCharacter::Tick(float DeltaTime) 97 { 98 Super::Tick(DeltaTime); 99 } 100 101 // Called to bind functionality to input 102 void ASlAiPlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) 103 { 104 Super::SetupPlayerInputComponent(PlayerInputComponent); 105 }
添加完畢