9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UE4でC++を使ってオブジェクトを回してみる

Last updated at Posted at 2018-08-08

概要

Blueprintを使わずC++でオブジェクトを回してみる

手順

対象アクタの作成

コンテンツブラウザの新規作成からC++クラスを作成します.
image.png

親クラスにはActorを選択します.
image.png

適当に分かる名前をつけます.ここではRotateCubeとします.
image.png

立ち上がってきたVisualStuidoなりX codeなりで,RotateCube.hRotateCube.cppを編集していく.
もし立ち上がらなければコンテンツブラウザのC++クラスディレクトリ(実際はプロジェクト名/source以下)内にC++クラスが生成されているので,そこから開ける.

C++で動作を書く

まずはヘッダファイルの方に利用する変数を宣言しておく.テンプレートは生成されているので,publicで座標格納用と回転角度格納用の変数だけ宣言しておく.

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

# pragma once

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

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

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

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

	UPROPERTY(EditAnywhere, Category = "Rotation")
	FRotator RotationValue;
};

ここで宣言したオブジェクトはこれだけです.

  • FRotator RotationValue

FRotatorは,(Pitch, Yaw, Roll)の3つのfloat精度の値を持ち,順にY軸中心,X軸中心,Z軸中心の回転角度を保持できるC++構造体です.XYZじゃないので注意です.本体の定義はEngine\Source\Runtime\Core\Public\Math\Rotator.hにあります.
参考:FRotator

そんなに長い実装ではないので,読んでみると動作を把握できます.
なお,C++構造体はデフォルトがpublicアクセシビリティのクラスなので,使い勝手は通常のクラスとほぼ同等です.
参考:C++ における class と struct の違い

また,オブジェクト宣言の1行上でUPROPERTYによるエディタからのアクセスの設定を行っています.これはアノテーションなのでセミコロンが不要なことに注意です.
UPROPERTYの詳細な説明はしませんが,ここでは以下のようなことを設定しています.

EditAnywhere

エディタやブループリントに値を公開し,編集可能にする.

Category = "Rotation"

公開時のカテゴリを設定.任意の文字列を当てられる.


次に,RotateCube.cppに移動・回転処理を実装します.

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

# include "RotateCube.h"

// Sets default values
ARotateCube::ARotateCube()
{
 	// 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;
	RotationValue = FRotator(.0f, .0f, .0f);
}

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

// Called every frame
void ARotateCube::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	AddActorLocalRotation(RotationValue*DeltaTime, false, 0, ETeleportType::TeleportPhysics);
}

まず,RotateCube.hで宣言したRotateValueの値を,コンストラクタ内ですべて0に初期化しています.コンストラクタはエンジン上でアクタを設置した時に一度だけ実行されます.

次に,Tick()内でRotateValueに保存されている角度だけ回転を行う処理を記述します.
ここでは,AddActorLocalRotationというメソッドを使って回転を行っています

AddActorLocalRotationは4つの引数を取るのですが,最初以外僕自身よくわかっていないのでわかりません.どうも他オブジェクトと接触したときの挙動や,回転時の動き方?の設定を与えているようなのですが,違いがわかりませんでした.誰か教えてください.

8/10追記.
AddActorLocalRotationは,引数に以下の値を取ります.

引数名
DeltaRotation FRotator or FQuat&
bSweep bool
OutSweepHitResult FHitResult*
Teleport ETeleportType

DeltaRotation

現在の回転角に加算する角度を渡します.FRotatorとFQuatの2種類のC++構造体インスタンスを受け付けることができます.FQuatを渡した場合はそのまま参照渡しされ,FRotatorを渡した場合は渡した先でFQuatに変換されて処理されます.

bSweep

移動・回転中にアクタが他のコリジョンと接触した場合,そこで動作を停止するかを指定します.壁にあたったら止まるかどうかということです.

OutSweepHitResult

bSweepにtrueが渡った場合,ここに渡された接触情報が判定されて動作を決定します.必要ない場合nullptrを渡しておきます.

Teleport

移動方式を指定します.ETeleportTypeはint8の列挙体で定義されており,NoneとTeleportPhysicsの2種類の値が存在します.Noneに設定した場合,指示されたアクタの移動・回転は高速移動になり,動作には慣性が適用されます.一方TeleportPhysicsを設定した場合は指定値分のテレポートになり,慣性は適用されません.

今回の実装では,FRotatorであるRotateValueを変換せず渡す方式にします.ただし,そのまま渡すとゲームを動かすマシンによって時間あたりの回転速度が変わってしまうので,Tick()に渡される一つ前のフレームとの差分DeltaTimeを乗算した値を渡すことにします.~~そして不明な後ろの引数はネットにあったものを参考にしました(許して).~~今回は他オブジェクトとの接触は考慮せずSweepfalse,差分はテレポートで問題ないので結果以下のようになります.

AddActorLocalRotation(RotationValue*DeltaTime, false, 0, ETeleportType::TeleportPhysics);

これで実装は終了です.
エディタ上部のコンパイルボタンを押して正常にコンパイルできることを確認してください.
image.png

設置して動かしてみる

コンテンツブラウザからC++クラスが格納されているディレクトリを開き,実装したRotateCubeをレベルにドラッグ&ドロップで追加します.
正常に追加されると右上のアウトライナにRotateCubeから生成されたアクタが表示されるので,クリックして詳細を確認します.
すると,詳細内のRotationタブ内から,UPROPERTYで公開設定したRotationValueの値が編集できるようになっています.
image.png
値はコンストラクタで設定した初期値0になっていると思われますので,任意の値に編集してみます.
image.png

これでアクタは回転するようになりましたが,メッシュが設定されておらず回転しても人間に見えないので,コンポーネントを追加よりキューブを追加してみます.
image.png
するとやっとレベル上に立方体が見えるようになりました.
image.png
これは見た目となるメッシュを追加したにすぎないため、他に回したいメッシュがあればそちらを選択すれば無事回ることでしょう。たぶん。

実行

位置を調整し,実行してみると回転するはずです.
お疲れ様でした.
ezgif-5-7996235e4a.gif

感想

エディタの実装に飛んで見て回るの楽しい

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?