Unreal Engine C++ Developer: Learn C++ and Make Video Games | Udemy UE4.25 Simple Shooterで自分なりに理解したこと。00800 ~TakeDamageのオーバーライド ~

基本的にはデフォルトのTakeDamageが来た時に処理を追加したいのでオーバーライドします。

UE4/Engine/Sounce/Runtime/Engine/Classes/GameFramework/Actor.h

virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser);
をコピーして

ShooterCharacter.h

にこれをペーストしてoverrideキーワードを追加しました。
    virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) override;

ShooterCharacter.cppはこうやって元のSuper::TakeDamegeを追加します

float AShooterCharacter::TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) ;
{
	float DamageApplied = Super::TakeDamage(DamageAmount,DamageEvent,EventInstigator,DamageCauser);
	
}

次に、ダメージを受けた時のヒットポイントを健康状態のとしてHealth変数を用意します。

ShooterCharacter.h

	UPROPERTY(EditDefaultsOnly)
	float MaxHealth=100;

	UPROPERTY(VisibleAnyWhere)
	float Health;

ShooterCharacter.cppでBeginPlayにHealth = MaxHealth;追加

void AShooterCharacter::BeginPlay()
{
	Super::BeginPlay();
	
	Health = MaxHealth;

	Gun = GetWorld()->SpawnActor<AGun>(GunClass);
	GetMesh()->HideBoneByName(TEXT("weapon_r"),EPhysBodyOp::PBO_None );
	Gun->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform, TEXT("weaponSocket"));
	Gun->SetOwner(this);
}

ShooterCharacter.cppでTakeDamageに以下追加

DamageToApply = FMath::Min(Health,DamageToApply);   
Health -= DamageToApply;   
UE_LOG(LogTemp,Display,TEXT(“Health Left %F”),Health);

float TimeToDisplay =5.0f;   
FString Health_str = FString::SanitizeFloat(Health);   
(\UE_4.25\Engine\Source\Runtime\Core\Private\Containers\String.cppにある)
FString TestHUDString =TEXT(“Health Left”)+ Health_str;   

GEngine->AddOnScreenDebugMessage(-1,TimeToDisplay,FColor::Green,TestHUDString);
(\UE_4.25\Engine\Source\Runtime\Engine\Private\UnrealEngine.cppにある)
詳細は以下
FString | UnrealEngineのドキュメント

https://docs.unrealengine.com/4.27/ja/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/StringHandling/FString/

return DamageToApply;

float AShooterCharacter::TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser)
{
	float DamageToApply = Super::TakeDamage(DamageAmount,DamageEvent,EventInstigator,DamageCauser);
	DamageToApply = FMath::Min(Health,DamageToApply);
	Health -= DamageToApply;
	UE_LOG(LogTemp,Display,TEXT("Health Left %F"),Health);
	float TimeToDisplay =5.0;
	FString Health_str = FString::SanitizeFloat(Health);
	FString TestHUDString =TEXT("Health Left")+	Health_str;
	GEngine->AddOnScreenDebugMessage(-1,TimeToDisplay,FColor::Green,TestHUDString);
	return DamageToApply;
}

ShooterCharacter.h 全文

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "ShooterCharacter.generated.h"

class AGun;


UCLASS()
class SIMPLESHOOTERCP2_API AShooterCharacter : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	AShooterCharacter();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	
	virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) override;

private:
	void MoveForward(float AxisValue);
	void MoveRight(float AxisValue);
	void LockUpRate(float AxisValue);
	void LockRightRate(float AxisValue);
	void Shoot();
	
	UPROPERTY(EditAnyWhere)
	float RotationRate = 10;

	UPROPERTY(EditDefaultsOnly)
	float MaxHealth=100;

	UPROPERTY(VisibleAnyWhere)
	float Health;

	UPROPERTY(EditDefaultsOnly)
	TSubclassOf<AGun> GunClass;

	UPROPERTY()
	AGun* Gun;


};

ShooterCharacter.cpp 全文

// Fill out your copyright notice in the Description page of Project Settings.


#include "ShooterCharacter.h"
#include "Gun.h"
//#include "Engine/Engine.h"
// Sets default values
AShooterCharacter::AShooterCharacter()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AShooterCharacter::BeginPlay()
{
	Super::BeginPlay();
	
	Health = MaxHealth;

	Gun = GetWorld()->SpawnActor<AGun>(GunClass);
	GetMesh()->HideBoneByName(TEXT("weapon_r"),EPhysBodyOp::PBO_None );
	Gun->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform, TEXT("weaponSocket"));
	Gun->SetOwner(this);
}

// Called every frame
void AShooterCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void AShooterCharacter::Shoot()
{
	Gun->PullTrigger();
}

// Called to bind functionality to input
void AShooterCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent ->BindAxis(TEXT("MoveForward"),this,&AShooterCharacter::MoveForward);
	PlayerInputComponent ->BindAxis(TEXT("LockUp"),this,&APawn::AddControllerPitchInput);
	PlayerInputComponent ->BindAxis(TEXT("MoveRight"),this,&AShooterCharacter::MoveRight);
	PlayerInputComponent ->BindAxis(TEXT("LockRight"),this,&APawn::AddControllerYawInput);
	PlayerInputComponent ->BindAxis(TEXT("LockUpRate"),this,&AShooterCharacter::LockUpRate);
	PlayerInputComponent ->BindAxis(TEXT("LockRightRate"),this,&AShooterCharacter::LockRightRate);
	PlayerInputComponent ->BindAction(TEXT("Jump"),EInputEvent::IE_Pressed,this,&ACharacter::Jump);
	PlayerInputComponent ->BindAction(TEXT("Shoot"),EInputEvent::IE_Pressed,this,&AShooterCharacter::Shoot);
}

float AShooterCharacter::TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser)
{
	float DamageToApply = Super::TakeDamage(DamageAmount,DamageEvent,EventInstigator,DamageCauser);
	DamageToApply = FMath::Min(Health,DamageToApply);
	Health -= DamageToApply;
	UE_LOG(LogTemp,Display,TEXT("Health Left %F"),Health);
	float TimeToDisplay =5.0f;
	FString Health_str = FString::SanitizeFloat(Health);
	FString TestHUDString =TEXT("Health Left")+	Health_str;
	GEngine->AddOnScreenDebugMessage(-1,TimeToDisplay,FColor::Green,TestHUDString);
	return DamageToApply;
}

void AShooterCharacter::MoveForward(float AxisValue)
{
	AddMovementInput(GetActorForwardVector() * AxisValue);
}
void AShooterCharacter::MoveRight(float AxisValue)
{
	AddMovementInput(GetActorRightVector() * AxisValue);
}

void AShooterCharacter::LockUpRate(float AxisValue)
{
	AddControllerPitchInput(AxisValue * RotationRate * GetWorld()->GetDeltaSeconds());
}
void AShooterCharacter::LockRightRate(float AxisValue)
{
	AddControllerYawInput(AxisValue * RotationRate * GetWorld()->GetDeltaSeconds());
}
// void AShooterCharacter::LockUp(float AxisValue)
// {
// 	AddControllerPitchInput(AxisValue);
// }

こうなった。

Unreal Engine C++ Developer: Learn C++ and Make Video Games | Udemy UE4.25 Simple Shooterで自分なりに理解したこと。00500 ~ヒットした場所にパーティクル~

UE4/Engine/Source/Runtime/Engine/Classes/Kismet/GameplayStatics.h

static UParticleSystemComponent* SpawnEmitterAtLocation(const UObject* WorldContextObject, UParticleSystem* EmitterTemplate, FVector Location, FRotator Rotation = FRotator::ZeroRotator, FVector Scale = FVector(1.f), bool bAutoDestroy = true, EPSCPoolMethod PoolingMethod = EPSCPoolMethod::None, bool bAutoActivateSystem = true);

デフォルト引数あるやつ消すとこう

static UParticleSystemComponent* SpawnEmitterAtLocation(const UObject* WorldContextObject, UParticleSystem* EmitterTemplate, FVector Location);

をつかった

Gun.hに これを追加して

	UPROPERTY(EditAnyWhere)
	UParticleSystem* ImpactEffect;

Gun.cppに実際にはShotDirection でショット方向をコントロールしてる

FVector ShotDirection = -Rotation.Vector();
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ImpactEffect, Hit.Location,ShotDirection.Rotation() );

	if(bSuccess==true)
	{
		UE_LOG(LogTemp,Warning,TEXT("HitWall!! "));
		DrawDebugPoint(GetWorld(), Hit.Location,40.0 ,FColor::Red , bPersistentLines2);
		FVector ShotDirection = -Rotation.Vector();
		UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ImpactEffect, Hit.Location,ShotDirection.Rotation() );

	}

で作ったプロパティ、ImpactEffectに設定

今回の状態 全文
Gun.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Gun.generated.h"

UCLASS()
class SIMPLESHOOTERCP2_API AGun : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AGun();

	void PullTrigger();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;
private:
	UPROPERTY(VisibleAnyWhere)
	USceneComponent* Root;

	UPROPERTY(VisibleAnyWhere)
	USkeletalMeshComponent* Mesh;

	UPROPERTY(EditAnyWhere)
	UParticleSystem* MuzzleFlash;

	UPROPERTY(EditAnyWhere)
	UParticleSystem* ImpactEffect;

	UPROPERTY(EditAnyWhere)
	float MaxRange = 1000;
};

Gun.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "Gun.h"

#include "Components/SkeletalMeshComponent.h"
#include "Kismet/GameplayStatics.h"
#include "DrawDebugHelpers.h"
// Sets default values
AGun::AGun()
{
 	// 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;

	Root = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
	SetRootComponent(Root);

	Mesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Mesh"));
	Mesh->SetupAttachment(Root);


}
void AGun::PullTrigger()
{
	UE_LOG(LogTemp,Warning,TEXT("You have been shot!! "));
	//MuzzleFlashSocket
	UGameplayStatics::SpawnEmitterAttached(MuzzleFlash, Mesh, TEXT("MuzzleFlashSocket"));
    
	APawn* OwnerPawn = Cast<APawn>(GetOwner());
	if(OwnerPawn==nullptr)
	{
		return;
	}
	AController* OwnerController= OwnerPawn ->GetController();
	if(OwnerController==nullptr)
	{
		return;
	}
	FVector Location= OwnerPawn->GetActorLocation();
	FRotator Rotation;
	OwnerController->GetPlayerViewPoint(  Location, Rotation );
	FVector End = Location + Rotation.Vector() * MaxRange;
	// TOTO: LineTrace

	float FOVDeg=90;
	float Scale=2.f;
	FColor const& Color=FColor::Blue;
	bool bPersistentLines=true;
	float LifeTime=-1.f;
	uint8 DepthPriority = 0;
	//DrawDebugCamera(GetWorld(), Location, Rotation, FOVDeg, Scale, Color, bPersistentLines, LifeTime, DepthPriority);

	float Size2 = 20.0;
	FColor const& Color2= FColor::Green;
	bool bPersistentLines2 = true;
	float LifeTime2 = -1.f;
	uint8 DepthPriority2 = 0;
	//DrawDebugPoint(GetWorld(), Location,Size2 ,Color2 , bPersistentLines2, LifeTime2, DepthPriority2);
	//DrawDebugPoint(GetWorld(), Location,Size2 ,Color2 , bPersistentLines2);
    //DrawDebugDirectionalArrow(GetWorld(), Location, End, 3.0, FColor::Blue, bPersistentLines);

	FHitResult Hit;
	ECollisionChannel TraceChannel = ECollisionChannel::ECC_GameTraceChannel1;
	bool bSuccess = GetWorld()->LineTraceSingleByChannel(Hit,Location,End,TraceChannel);
	if(bSuccess==true)
	{
		UE_LOG(LogTemp,Warning,TEXT("HitWall!! "));
		//DrawDebugPoint(GetWorld(), Hit.Location,40.0 ,FColor::Red , bPersistentLines2);
		FVector ShotDirection = -Rotation.Vector();
		UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ImpactEffect, Hit.Location,ShotDirection.Rotation() );

	}
	//DrawDebugPoint(GetWorld(), End,Size2 ,FColor::Red , bPersistentLines2);
}

// Called when the game starts or when spawned
void AGun::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AGun::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

でできたのがこれ

#UE4 Png to TGA or TGA to Png

UE4を使っていると2DデザイナーはPNGを使ってくるけども

PNGの透過はUE4では使えない。

だからTGAに変換します。どんなかんじにこんな感じに

PNGのアルファ反転してtga保存


#target photoshop
//
// PNG_AlphaChannelInverse__Go__TGA.jsx
//

//
// Generated Wed Feb 02 2022 12:59:51 GMT+0900
//

cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };

//
//==================== アルファ反転してtga保存 ==============
//
function ________tga() {
  //
  function step1(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    desc1.putInteger(cTID('Dpth'), 8);
    var desc2 = new ActionDescriptor();
    desc2.putInteger(cTID('Vrsn'), 6);
    desc2.putEnumerated(cTID('Mthd'), sTID("hdrToningMethodType"), sTID("hdrtype2"));
    desc2.putDouble(cTID('Exps'), 0);
    desc2.putDouble(cTID('Gmm '), 1);
    desc2.putBoolean(sTID("deghosting"), false);
    desc1.putObject(cTID('With'), sTID("hdrOptions"), desc2);
    executeAction(sTID('convertMode'), desc1, dialogMode);
  };

  //
  function step2(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putName(cTID('Chnl'), "アルファチャンネル 1");
    desc1.putReference(cTID('null'), ref1);
    executeAction(sTID('select'), desc1, dialogMode);
  };

  //
  function step3(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    executeAction(sTID('invert'), undefined, dialogMode);
  };

  //
  function step4(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var desc2 = new ActionDescriptor();
    desc2.putInteger(cTID('BtDp'), 32);
    desc2.putInteger(cTID('Cmpr'), 0);
    desc1.putObject(cTID('As  '), cTID('TrgF'), desc2);
    desc1.putPath(cTID('In  '), new File("ファイルパス"));
    desc1.putInteger(cTID('DocI'), 223);
    executeAction(sTID('save'), desc1, dialogMode);
  };

  step1();      // 
  step2();      // 
  step3();      // 
  step4();      //
};



//=========================================
//                    ________tga.main
//=========================================
//

________tga.main = function () {
  ________tga();
};

________tga.main();

// EOF

"PNG_AlphaChannelInverse__Go__TGA.jsx"
// EOF

TGA 透過は削除してPNGへ

#target photoshop
//
// AlphaChannelDelete_Go_TGA_PNG.jsx
//

//
// Generated Wed Feb 02 2022 12:58:24 GMT+0900
//

cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };

//
//==================== アルファチャンネルを無くしてPNG保存 ==============
//
function ______________PNG() {
  //
  function step1(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    desc1.putInteger(cTID('Dpth'), 16);
    var desc2 = new ActionDescriptor();
    desc2.putInteger(cTID('Vrsn'), 6);
    desc2.putEnumerated(cTID('Mthd'), sTID("hdrToningMethodType"), sTID("hdrtype2"));
    desc2.putDouble(cTID('Exps'), 0);
    desc2.putDouble(cTID('Gmm '), 1);
    desc2.putBoolean(sTID("deghosting"), false);
    desc1.putObject(cTID('With'), sTID("hdrOptions"), desc2);
    executeAction(sTID('convertMode'), desc1, dialogMode);
  };

  //
  function step2(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var desc2 = new ActionDescriptor();
    desc2.putEnumerated(cTID('Mthd'), sTID("PNGMethod"), sTID("quick"));
    desc2.putEnumerated(sTID("PNGInterlaceType"), sTID("PNGInterlaceType"), sTID("PNGInterlaceNone"));
    desc2.putEnumerated(sTID("PNGFilter"), sTID("PNGFilter"), sTID("PNGFilterAdaptive"));
    desc2.putInteger(cTID('Cmpr'), 6);
    desc1.putObject(cTID('As  '), sTID("PNGFormat"), desc2);
    desc1.putPath(cTID('In  '), new File("ファイルパス"));
    desc1.putInteger(cTID('DocI'), 314);
    desc1.putBoolean(cTID('Cpy '), true);
    desc1.putBoolean(cTID('AlpC'), false);
    executeAction(sTID('save'), desc1, dialogMode);
  };

  //
  function step3(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    desc1.putEnumerated(cTID('Svng'), cTID('YsN '), cTID('N   '));
    desc1.putInteger(cTID('DocI'), 314);
    desc1.putBoolean(sTID("forceNotify"), true);
    executeAction(sTID('close'), desc1, dialogMode);
  };

  step1();      //
  step2();      //
  step3();      //
};



//=========================================
//                    ______________PNG.main
//=========================================
//

______________PNG.main = function () {
  ______________PNG();
};

______________PNG.main();

// EOF

"AlphaChannelDelete_Go_TGA_PNG.jsx"
// EOF

photoshop の Action の [.atn]をjsxへ変換する atn2js.jsx ActionToJavascript.jsxについて ~FurcraeaTokyo版~

photoshop の Action の [.atn]をjsxへ変換する atn2js.jsx ActionToJavascript.jsxについて 

ExtendScript Toolkit CC (ESTK CC 4.0.0.1)

http://sourceforge.net/projects/ps-scripts/files/xtools/v2.2betas/

がダウンロードできるが
Macだと直下にフォルダ作っていれとく。
/Developer/xtools/xapps/ActionToJavascript.jsx
そのままじゃ動かなかった件

頭に
#target photoshop
いれれば動く

入れないと
//@include “xlib/xml/atn2bin.jsx” がエラーとか
DescValueType.ALIASTYPE がみつかりません。とか

動けばこんな感じ

。。
修正したものおいておく。
xtools-2_2b1_furcraeaTokyo.zip

https://drive.google.com/file/d/11iejj87qI_DdIAbpvP6uWKUWyRAdFSoT/view?usp=sharing

Adobe jsx 用のVisual Studio Codeでの環境構築方法 ExtendScript Debbuerをインストールするときの注意点

Adobe ExtendScript ToolKit の開発が終了して、今後はVisual Studio Code
のプラグインが推奨みたいなので、

VSCodeに

ExtendScript Debbuerをインストール

このとき再起動しないと

#target photoshopで(#15)Can’t initialize target といわれる

https://www.cg-method.com/extendscript-visual-studio-code/

さんに助けられてこのコード類と手順に感謝します。

1. 作業環境場所にフォルダを作成(vscodeとか)

  1. 先に作ったフォルダをドラッグ&ドロップ
  2. サイドのデバッグボタン(丸い虫)を押してパネルを展開
  3. 歯車をクリックして、「ExtendScript Debbuer 」を選択
  4. 選択後、launch.jsonが生成されます。

launch.jsonのコードを変更

{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "extendscript-debug",
            "request": "launch",
            "name": "Run current script",
            "program": "${file}", //現在開いているファイルを対象に,
            "stopOnEntry": false
        }
    ]
}

ps_test.jsx

#target photoshop
function test(){
    try {
        alert("sucsess!");
    } catch (e){
        alert("No Good!");
    }
}
 test();

はい

できた

Unreal Engine C++ Developer: Learn C++ and Make Video Games | Udemy UE4.25 Simple Shooterで自分なりに理解したこと。00400 ~チャネルによるライントレース~

world.h>LineTraceTestと検索

LineTraceTestByChannel

/ **
*特定のチャネルを使用して世界に対して光線をトレースし、ブロッキングヒットが見つかった場合に戻ります。
* @paramStart光線の開始位置
* @paramEnd光線の終了位置
* @paramTraceChannelこの光線が含まれる「チャネル」。ヒットするコンポーネントを決定するために使用されます。
* @paramParamsトレースに使用される追加のパラメーター
*このトレースに使用される@paramResponseParam ResponseContainer
* @ returnブロッキングヒットが見つかった場合はTRUE
* /	

// LINE TRACE

	/**
	 *  Trace a ray against the world using a specific channel and return if a blocking hit is found.
	 *  @param  Start           Start location of the ray
	 *  @param  End             End location of the ray
	 *  @param  TraceChannel    The 'channel' that this ray is in, used to determine which components to hit
	 *  @param  Params          Additional parameters used for the trace
	 * 	@param 	ResponseParam	ResponseContainer to be used for this trace
	 *  @return TRUE if a blocking hit is found
	 */
	bool LineTraceTestByChannel(const FVector& Start,const FVector& End,ECollisionChannel TraceChannel, const FCollisionQueryParams& Params = FCollisionQueryParams::DefaultQueryParam, const FCollisionResponseParams& ResponseParam = FCollisionResponseParams::DefaultResponseParam) const;
	

LineTraceSingleByChannel

/ **
*特定のチャネルを使用して世界に対して光線をトレースし、最初のブロッキングヒットを返します
* @paramOutHit最初のブロッキングヒットが見つかりました
* @paramStart光線の開始位置
* @paramEnd光線の終了位置
* @paramTraceChannelこの光線が含まれる「チャネル」。ヒットするコンポーネントを決定するために使用されます。
* @paramParamsトレースに使用される追加のパラメーター
*このトレースに使用される@paramResponseParam ResponseContainer
* @ returnブロッキングヒットが見つかった場合はTRUE
* /	

/**
	 *  Trace a ray against the world using a specific channel and return the first blocking hit
	 *  @param  OutHit          First blocking hit found
	 *  @param  Start           Start location of the ray
	 *  @param  End             End location of the ray
	 *  @param  TraceChannel    The 'channel' that this ray is in, used to determine which components to hit
	 *  @param  Params          Additional parameters used for the trace
	 * 	@param 	ResponseParam	ResponseContainer to be used for this trace	 
	 *  @return TRUE if a blocking hit is found
	 */
	bool LineTraceSingleByChannel(struct FHitResult& OutHit,const FVector& Start,const FVector& End,ECollisionChannel TraceChannel,const FCollisionQueryParams& Params = FCollisionQueryParams::DefaultQueryParam, const FCollisionResponseParams& ResponseParam = FCollisionResponseParams::DefaultResponseParam) const;

TraceChannelの設定はこう

LineTraceSingleByChannelの引数にはECollisionChannel がある

LineTraceSingleByChannel(struct FHitResult& OutHit,const FVector& Start,const FVector& End,ECollisionChannel TraceChannel,const FCollisionQueryParams& Params = FCollisionQueryParams::DefaultQueryParam, const FCollisionResponseParams& ResponseParam = FCollisionResponseParams::DefaultResponseParam) const;

ECollisionChannel の定義を開く

Config/DefaultEngine.ini ひらくとさっき設定したものがデータになってる

+EditProfiles=(Name="NoCollision",CustomResponses=((Channel="Bullet",Response=ECR_Ignore)))
+EditProfiles=(Name="OverlapAll",CustomResponses=((Channel="Bullet",Response=ECR_Ignore)))
+EditProfiles=(Name="InvisibleWall",CustomResponses=((Channel="Bullet",Response=ECR_Ignore)))
+EditProfiles=(Name="InvisibleWallDynamic",CustomResponses=((Channel="Bullet",Response=ECR_Ignore)))

Gun.hに

	UPROPERTY(EditAnyWhere)
	float MaxRange = 1000;

Gun.cppに戻る

UE4/Engine/Sounce/Runtime/Engine/Public/DrawDebugHelpers.h

DrawDebugPointを使う

	FVector End = Location + Rotation.Vector() * MaxRange;
	// TOTO: LineTrace
  / **デバッグポイントを描画します* /
  /** Draw a debug point */
	float Size=20.0;
	FColor PointColor::Red;
	bool bPersistentLines = true;
	float LifeTime = -1.f;
	uint8 DepthPriority = 0;
	DrawDebugPoint(GetWorld(), Location,Size ,Color , bPersistentLines, LifeTime, DepthPriority)
	

なんか右にでる

LineTraceSingleByChannelを使う

UE4/Engine/Source/Runtime/Engine/Classes/Engine/world.hにある

/ **
*特定のチャネルを使用して世界に対して光線をトレースし、最初のブロッキングヒットを返します
* @paramOutHit最初のブロッキングヒットが見つかりました
* @paramStart光線の開始位置
* @paramEnd光線の終了位置
* @paramTraceChannelこの光線が含まれる「チャネル」。ヒットするコンポーネントを決定するために使用されます。
* @paramParamsトレースに使用される追加のパラメーター
*このトレースに使用される@paramResponseParam ResponseContainer
* @ returnブロッキングヒットが見つかった場合はTRUE
* /	
/**
	 *  Trace a ray against the world using a specific channel and return the first blocking hit
	 *  @param  OutHit          First blocking hit found
	 *  @param  Start           Start location of the ray
	 *  @param  End             End location of the ray
	 *  @param  TraceChannel    The 'channel' that this ray is in, used to determine which components to hit
	 *  @param  Params          Additional parameters used for the trace
	 * 	@param 	ResponseParam	ResponseContainer to be used for this trace	 
	 *  @return TRUE if a blocking hit is found
	 */
	bool LineTraceSingleByChannel(struct FHitResult& OutHit,const FVector& Start,const FVector& End,ECollisionChannel TraceChannel,const FCollisionQueryParams& Params = FCollisionQueryParams::DefaultQueryParam, const FCollisionResponseParams& ResponseParam = FCollisionResponseParams::DefaultResponseParam) const;

Gun.hはこんなんで

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Gun.generated.h"

UCLASS()
class SIMPLESHOOTERCP2_API AGun : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AGun();

	void PullTrigger();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;
private:
	UPROPERTY(VisibleAnyWhere)
	USceneComponent* Root;

	UPROPERTY(VisibleAnyWhere)
	USkeletalMeshComponent* Mesh;

	UPROPERTY(EditAnyWhere)
	UParticleSystem* MuzzleFlash;

	UPROPERTY(EditAnyWhere)
	float MaxRange = 1000;
};

Gun.cppはこんな感じになった

// Fill out your copyright notice in the Description page of Project Settings.


#include "Gun.h"

#include "Components/SkeletalMeshComponent.h"
#include "Kismet/GameplayStatics.h"
#include "DrawDebugHelpers.h"
// Sets default values
AGun::AGun()
{
 	// 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;

	Root = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
	SetRootComponent(Root);

	Mesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Mesh"));
	Mesh->SetupAttachment(Root);


}
void AGun::PullTrigger()
{
	UE_LOG(LogTemp,Warning,TEXT("You have been shot!! "));
	//MuzzleFlashSocket
	UGameplayStatics::SpawnEmitterAttached(MuzzleFlash, Mesh, TEXT("MuzzleFlashSocket"));
    
	APawn* OwnerPawn = Cast<APawn>(GetOwner());
	if(OwnerPawn==nullptr)
	{
		return;
	}
	AController* OwnerController= OwnerPawn ->GetController();
	if(OwnerController==nullptr)
	{
		return;
	}
	FVector Location= OwnerPawn->GetActorLocation();
	FRotator Rotation;
	OwnerController->GetPlayerViewPoint(  Location, Rotation );
	FVector End = Location + Rotation.Vector() * MaxRange;
	// TOTO: LineTrace

	float FOVDeg=90;
	float Scale=2.f;
	FColor const& Color=FColor::Blue;
	bool bPersistentLines=true;
	float LifeTime=-1.f;
	uint8 DepthPriority = 0;
	DrawDebugCamera(GetWorld(), Location, Rotation, FOVDeg, Scale, Color, bPersistentLines, LifeTime, DepthPriority);

	float Size2 = 20.0;
	FColor const& Color2= FColor::Green;
	bool bPersistentLines2 = true;
	float LifeTime2 = -1.f;
	uint8 DepthPriority2 = 0;
	//DrawDebugPoint(GetWorld(), Location,Size2 ,Color2 , bPersistentLines2, LifeTime2, DepthPriority2);
	DrawDebugPoint(GetWorld(), Location,Size2 ,Color2 , bPersistentLines2);
    DrawDebugDirectionalArrow(GetWorld(), Location, End, 3.0, FColor::Blue, bPersistentLines);

	FHitResult Hit;
	ECollisionChannel TraceChannel = ECollisionChannel::ECC_GameTraceChannel1;
	bool bSuuccess = GetWorld()->LineTraceSingleByChannel(Hit,Location,End,TraceChannel);
	if(bSuuccess==true)
	{
		UE_LOG(LogTemp,Warning,TEXT("HitWall!! "));
		DrawDebugPoint(GetWorld(), Hit.Location,40.0 ,FColor::Red , bPersistentLines2);
	}
	DrawDebugPoint(GetWorld(), End,Size2 ,FColor::Red , bPersistentLines2);
}

// Called when the game starts or when spawned
void AGun::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AGun::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

Unreal Engine C++ Developer: Learn C++ and Make Video Games | Udemy UE4.25 Simple Shooterで自分なりに理解したこと。00300 ~プレイヤーの視点取得~

UEソースコードを読むためのC++の勉強なので、パスを書いておく

UE_4.25\Engine\Source\Runtime\Engine\Public\DrawDebugHelpers.h
DrawDebugCamera()を使うための

/** Draw a debug camera shape.  FOV is full angle in degrees. */ENGINE_API void
/ **デバッグカメラの形状を描画します。 FOVは度単位の全角です。 * /エンジンのAPI
DrawDebugCamera(const UWorld* InWorld, FVector const& Location, FRotator const& Rotation, float FOVDeg, float Scale=1.f, FColor const& Color=FColor::White, bool bPersistentLines=false, float LifeTime=-1.f, uint8 DepthPriority = 0);

UE_4.25\Engine\Source\Runtime\Engine\Classes\GameFramework\Controller.hのGetPlayerViewPoint()

    /**     
* Returns Player’s Point of View     
* For the AI this means the Pawn’s ‘Eyes’ ViewPoint     
* For a Human player, this means the Camera’s ViewPoint     
*     
* @output  out_Location, view location of player     
* @output  out_rotation, view rotation of player     
*/   

/ *
プレイヤーの視点を返します
AIの場合、これはポーンの「目」ビューポイントを意味します
人間のプレイヤーの場合、これはカメラのビューポイントを意味します

@output out_Location、プレーヤーの場所を表示
@output out_rotation、プレーヤーの回転を表示
*/
virtual void GetPlayerViewPoint( FVector& Location, FRotator& Rotation ) const;

Gun.cpp

#include "DrawDebugHelpers.h"
void AGun::PullTrigger()
{
	UE_LOG(LogTemp,Warning,TEXT("You have been shot!! "));
	//MuzzleFlashSocket
	UGameplayStatics::SpawnEmitterAttached(MuzzleFlash, Mesh, TEXT("MuzzleFlashSocket"));
    
	APawn* OwnerPawn = Cast<APawn>(GetOwner());
	if(OwnerPawn==nullptr)
	{
		return;
	}
	AController* OwnerController= OwnerPawn ->GetController();
	if(OwnerController==nullptr)
	{
		return;
	}
	FVector Location;
	FRotator Rotation;
	OwnerController->GetPlayerViewPoint(  Location, Rotation );
	
	//DrawDebugCamera(UWorld, Location, Rotation, float FOVDeg, float Scale=1.f, FColor const& Color=FColor::White, bool bPersistentLines=false, float LifeTime=-1.f, uint8 DepthPriority = 0);
	float FOVDeg=90;
	float Scale=2.f;
	FColor const& Color=FColor::Blue;
	bool bPersistentLines=true;
	float LifeTime=-1.f;
	uint8 DepthPriority = 0;
	DrawDebugCamera(GetWorld(), Location, Rotation, FOVDeg, Scale, Color, bPersistentLines, LifeTime, DepthPriority);

	
}

Unreal Engine C++ Developer: Learn C++ and Make Video Games | Udemy UE4.25 Simple Shooterで自分なりに理解したこと。00200 ~ParticleSystemスポーン~

勉強したこと

Gun.hで

/// Indicates that this property can be edited by property windows in the editor        EditAnywhere,

/////このプロパティがエディタのプロパティウィンドウで編集できることを示します

スポーンするものはポインタで。

	UPROPERTY(EditAnyWhere)
	UParticleSystem* MuzzleFlash;

Gun.cppで

//簡単な方法

static UParticleSystemComponent* SpawnEmitterAttached(class UParticleSystem* EmitterTemplate, class USceneComponent* AttachToComponent, FName AttachPointName = NAME_None);


// Backwards compatible version of SpawnEmitterAttached for C++ without Scale   
//スケールなしのC ++用のSpawnEmitterAttachedの下位互換バージョン
//デフォルト引数がなくて多く使いずらいもの

static UParticleSystemComponent* SpawnEmitterAttached(class UParticleSystem* EmitterTemplate, class USceneComponent* AttachToComponent, FName AttachPointName, FVector Location, FRotator Rotation, EAttachLocation::Type LocationType);

#include "Kismet/GameplayStatics.h"
UGameplayStatics::SpawnEmitterAttached(MuzzleFlash, Mesh, TEXT("MuzzleFlashSocket"));

そしたらエディタでエミッタを設定する

Unreal Engine C++ Developer: Learn C++ and Make Video Games | Udemy UE4.22 VS Code をエディターにセットする(Win Mac の違いをなくすため)

エディタの環境設定>一般>ソースコードAccessor>Source Code Editor >Visual Studio Code

Generate Visual Studio Code Project (Visual Studio Code プロジェクトを作成)

workspaceができる

Open Visual Studio Code (開く Visual Studio Code)

インテリセンスの影響で壊れるコードをサポートする拡張をインストール

vsc-ext-ue4-int-fixes.md – gists · GitHub

https://gist.github.com/boocs/f63a4878156295b6e854cac68672f305

installation

  1. Download from here: https://github.com/boocs/ue4-intellisense-fixes/releases/

ダウンロードしたVSIXを選ぶとインストール完了

ファイル>ユーザー設定>設定>

ue intellisense と検索して出てくるチェックを二つオンにした。

いちどVSCodeを再起動

UE4>Studio Code (開く Visual Studio Code)

Unreal Engine C++ Developer: Learn C++ and Make Video Games | Udemy TripleX Game End Code


#include <iostream>
#include <ctime>
void PrintIntroduction(int Diffculty)
{
    //Coment
    std::cout << "\n\nYou are a secret agent breaking into a "<< Diffculty;
    std::cout << " secure server room...\nEnter the correct code to continue...\n\n";   
}
bool PlayGame(int Diffculty)
{
    PrintIntroduction(Diffculty);
   
    const int CodeA = rand() % Diffculty;
    const int CodeB = rand() % Diffculty;
    const int CodeC = rand() % Diffculty;

    const int CodeSum = CodeA + CodeB + CodeC;
    const int CodeProduct = CodeA * CodeB * CodeC;
    /*
    Comment
    */
    std::cout << std::endl;
    std::cout << "There are 3 nember in the code";
    std::cout << "\nThe codes add-up to: " << CodeSum ;
    std::cout << "\nThe codes multiply to give: " << CodeProduct << std::endl;

    //Store Player guess
    int GuessA,GuessB,GuessC;
    std::cin >> GuessA >> GuessB >> GuessC;
    //std::cout << "You Entered: " << GuessA << GuessB << GuessC; 

    int GuessSum = GuessA + GuessB + GuessC;
    int GuessProduct = GuessA * GuessB * GuessC;

    //std::cout << "The codes add-up to: " << GuessSum << std::endl;
    //std::cout << "The codes multiply to give: " << GuessProduct << std::endl;

    //Check the player Guess
    if(GuessSum==CodeSum && GuessProduct== CodeProduct)
    {
        std::cout << "You Win \n";
        return true;
    }
    else
    {
        std::cout << "You Lose \n";
        return false;
    }
}

int main()
{
    srand(time(NULL));
    
    int LevelDifficalty = 1;
    int const MaxDiffculty=5;
    while (LevelDifficalty <= MaxDiffculty)//loop game 
    {
        std::cout << rand() % 10 << "\n";
        bool bLevelComplete = PlayGame(LevelDifficalty);
        std::cin.clear();//Clear any Error
        std::cin.ignore();//Discard the buffer

        if (bLevelComplete)
        {
            ++LevelDifficalty;
        }
        
    }
    std::cout << "You is God!! ";
    
    return 0;
}