技術ブログを目指すブログ

toncrimentan_w’s blog

アンリアルエンジン のC++の想定される量産設計(仮)

実際にアンリアルエンジンで開発が決まった場合における

C++プログラマ側の量産体制テストコードを書いて検証してみる

 

図はエネミーの処理)

 

メンバ変数はm_idのみReadWriteエディタ側からの指定を有効とするため

それ以外のメンバ変数はReadOnly IDからデータベースを介して設定されるべき。

 

また公開したい変数は public にする必要があるようだ

 

postInitProperty PostEditChangeProperty

からはステータスの更新処理の呼び出し

インスタンスが生成された場合 と エディタでIDを変更された場合の処理を記入

 

文字列はFStringで定義

 

この調子ならUE4の採用もありでプログラマの仕事のなくならない? 

 

ActorEnemy.h

/**
 * @file  ActorEnemy.h
 * @brief  アクター(エネミー)
 */

#pragma once

#include "GameFramework/Character.h"
#include "ActorEnemy.generated.h"

/**
 * @brief  アクター(エネミー)
 */
UCLASS()
class FIELDTEST01_API AActorEnemy
 : public ACharacter
{
public :

    GENERATED_BODY()

    /// エネミーID ※ブループリント開発者に指定してもらうためReadWriteとします。
    UPROPERTY( EditAnywhere, BlueprintReadWrite, Category="Status" )
    int32 m_id;

    /// 名前   ※IDからデータベースを介して設定されるためブループリント開発者からはreadOnlyとなります。
    UPROPERTY( BlueprintReadOnly, VisibleAnywhere, Transient, Category="Status" )
    FString m_name;

    /// HP   ※IDからデータベースを介して設定されるためブループリント開発者からはreadOnlyとなります。
    UPROPERTY( BlueprintReadOnly, VisibleAnywhere, Transient, Category="Status" )
    int32 m_hp;

    /// 攻撃力   ※IDからデータベースを介して設定されるためブループリント開発者からはreadOnlyとなります。
    UPROPERTY( BlueprintReadOnly, VisibleAnywhere, Transient, Category="Status" )
    int32 m_atk;

    /// 防御力   ※IDからデータベースを介して設定されるためブループリント開発者からはreadOnlyとなります。
    UPROPERTY( BlueprintReadOnly, VisibleAnywhere, Transient, Category="Status" )
    int32 m_def;


public:

    /**
     * @brief  コンストラクタ
     */
    AActorEnemy();


    ///
    /// Actor.hからの継承
    ///

    /**
     * @brief  プロパティのポスト初期化イベント
     */
    virtual void PostInitProperties() override;

#if WITH_EDITOR
    /**
    * @brief  アンリアルエディタによるプロパティの変更イベント
    * @param[in] PropertyChangedEvent パラメータ
    */
    virtual void PostEditChangeProperty( FPropertyChangedEvent& PropertyChangedEvent ) override;
#endif

    /**
     * @brief  入力イベント
     *    http://u16kuma.hateblo.jp/entry/2016/05/21/211810
     */
    virtual void SetupPlayerInputComponent( class UInputComponent* PlayerInputComponent ) override;

    /**
     * @brief  再生開始イベント
     *    (アクタがプレイ可能なステートになったことを知らせるイベント)
     */
    virtual void BeginPlay() override;

    /**
    * @brief  更新イベント
    */
    virtual void Tick( float DeltaSeconds ) override;


    ///
    /// ステータスの操作
    ///

    /**
     * @brief  HPの増減
     * @param[in] val   値
     */
    UFUNCTION(BlueprintCallable, Category="Status")
    void addHp( int32 val );

    /**
     * @brief  HPの取得
     * @return  HP
     */
    UFUNCTION(BlueprintCallable, Category="Status")
    int32 getHp() const ;


private :

    ///
    /// ステータスの操作
    ///

    /**
     * @brief  ステータスのセットアップ
     */
    void setupStatus();

};

 

 ActorEnemy.cpp

/**
 * @file  ActorEnemy.h
 * @brief  アクター(エネミー)
 */

#include "FieldTest01.h"
#include "ActorEnemy.h"


/**
 * @brief  コンストラクタ
 */
AActorEnemy::AActorEnemy()
 : m_id( 1 ) ///< IDは1~
{
    /// Tickイベントの有効化
    PrimaryActorTick.bCanEverTick = true;

    /*
     bCanEverTickをtrueにしないことで処理を軽減することができます。
     https://docs.unrealengine.com/latest/JPN/Programming/Introduction/index.html
    */
}


///
/// Actor.hからの継承
///

/**
 * @brief  入力イベント
 *    http://u16kuma.hateblo.jp/entry/2016/05/21/211810
 */
void AActorEnemy::SetupPlayerInputComponent( UInputComponent* PlayerInputComponent )
{
    UE_LOG( LogTemp, Warning, __FUNCTIONW__ );

    Super::SetupPlayerInputComponent(PlayerInputComponent);

}

/**
 * @brief  プロパティのポスト初期化イベント
 */
void AActorEnemy::PostInitProperties()
{
    UE_LOG( LogTemp, Warning, __FUNCTIONW__ );

    Super::PostInitProperties();

    /// ステータスのセットアップ
    setupStatus();
    /*
     インスタンスが生成された直後に
     ステータスが更新される必要があるため呼び出しています。
     */
}

#if WITH_EDITOR
/**
 * @brief  アンリアルエディタによるプロパティの変更イベント
 * @param[in] PropertyChangedEvent パラメータ
 */
void AActorEnemy::PostEditChangeProperty( FPropertyChangedEvent& PropertyChangedEvent )
{
    UE_LOG( LogTemp, Warning, __FUNCTIONW__ );

    Super::PostEditChangeProperty( PropertyChangedEvent );

    /// ステータスのセットアップ
    setupStatus();
    /*
     デザイナによるプロパティが呼ばれたときは
     ステータスが更新される必要があるため呼び出しています。
     */
}
#endif

/**
 * @brief  再生開始イベント
 *    (アクタがプレイ可能なステートになったことを知らせるイベント)
 */
void AActorEnemy::BeginPlay()
{
    Super::BeginPlay();
}

/**
 * @brief  更新イベント
 */
void AActorEnemy::Tick( float DeltaTime )
{
    Super::Tick( DeltaTime );
}


///
/// ステータスの操作
///

/**
 * @brief  ステータスのセットアップ
 */
void AActorEnemy::setupStatus()
{
    /// IDからエネミーごとのステータスを更新する
    switch( m_id )
    {
    case 1:
     m_name = "inu";
     m_hp = 100;
     break ;
    case 2:
     m_name = "saru";
     m_hp = 200;
     break ;
    case 3:
     m_name = "kiji";
     m_hp = 300;
     break ;
    default :
     m_name = "unknown";
     break ;
    }

    //UE_LOG( LogTemp, Warning, TEXT("%s:ステータスを更新"), __FUNCTIONW__ );
}

/**
 * @brief  HPの増減
 * @param[in] val   値
 */
void AActorEnemy::addHp( int32 val )
{
    m_hp += val;
    if( m_hp < 0 )
     m_hp = 0;
}

/**
 * @brief  HPの取得
 * @return  HP
 */
UFUNCTION(BlueprintCallable, Category="Status")
int32 AActorEnemy::getHp() const
{
    return m_hp;
}