おかえり。
さて、キャラクターは別として、ゲームで最も重要なクラスの 1 つは武器クラスです。 それでは、武器クラスを作成します。 この講義では、すべての武器に必要ないくつかの基本的なコンポーネントと、武器の状態の列挙型を追加します。 だから私たちは武器を扱う方法を知っています。 その状態次第です。
それでは始めましょう。 そのため、武器クラスが必要になります。 右クリックして [新しい C++ クラス] を追加します。 そして、私たちの武器は単に ACTOR にすることができます。 だから私はACTORを選ぶつもりです。 次へをクリックします。
そして、武器クラスと [Weapon] という独自のフォルダーを保持したいと思います。 後で、Weapon からさらに多くのクラスを派生させるときに、そのようにします。 これらすべての武器クラスを武器フォルダに貼り付けることができます。 さて、このクラスは「武器」と呼ばれます。 それでは[クラスを作成]をクリックしましょう。 したがって、このポップアップ メッセージで [いいえ] を押すことができます。
ここ Visual Studio には、武器クラスがあります。 今のところ、残りのタブを開く必要はありません。
[ Weapon.h] を右クリックして [これ以外をすべて閉じる] を選択します。 [Ctrl + K または O] を使用して、武器のヘッダー ファイルから [weapon.cpp] を開くことができます。
武器は武器フォルダにあるので、これまで見てきたように、ここではこの武器パーツは必要ありません。 そのため、[weapon.h] だけを含めるようにインクルードを変更すると、すべてのコンパイラ エラーが修正されます。
それでは、[weapon.h] ファイルに向かいましょう。ここには、コンストラクター beginPlay と tick 関数があります。 CHARACTER クラスで行ったのと同じように、これらのコメントは今は必要ないので削除します。
そして、すべての武器に必要な基本コンポーネントを追加したいと思います。 そのため、これらのコンポーネント変数用に [プライベート セクション] をここに作成できます。
先に進み、TICK をここの [public section] の Weapon コンストラクターのすぐ下に移動します。
[プライベート セクション] では、武器とすべてのアセットのメッシュが必要です。 ASSETS フォルダに移動して、[militaryWeaponsSilver] と [weapons] を確認します。 これらはすべて SKELETAL メッシュであることがわかります。 したがって、私の武器クラスには確実に SKELETAL メッシュ コンポーネントが必要です。
それでは、そのうちの 1 つを追加しましょう。 これは USkeletalMeshComponent になり、これを WeaponMesh と呼ぶことができます。
さて、weaponMesh はもちろん UProperty を取得しており、[visibleAnywhere] で作成します。 そして、ブループリントからコンポーネントにスケルタル メッシュを設定できるようになります。 では、これにカテゴリを付けて、そのカテゴリを [武器のプロパティ] と呼びます。
ここで、SKELETAL メッシュに加えて、キャラクターが近くにいるときにこの武器を装備できるように、ある種のオーバーラップ ボリュームが必要になります。
そこで、USphereComponent を前方宣言し、areaSphere という sphereComponent を使用します。 また、エリアスフィアは武器メッシュと同じプロパティを取得できます。
この武器を開発するにつれて、より多くのコンポーネントができあがります。 でも今のところ、これでよかったと思っています。 これらと [weapon.cpp] を作成してみましょう。
さて、これらのコンポーネントを作成する前に最初に行うことは、bCanEverTick を false に設定することです。 後で武器を作動させる必要があると判断した場合は、いつでもこれを変更できます。 しかし、今のところ false に設定します。
また、これらのコメントは実際には何の役にも立たないため、これらのコメントも削除します。
WeaponMesh を作成できます。 WeaponMesh = createDefaultSubObject として、USkeletalMeshComponent を使用します。 そして、これをweaponMeshと呼ぶことにします。
[weaponMesh->setupAttachment(rootComponent)] とします。
後で、この武器をドロップできるようにする予定です。ドロップするたびに、武器が壁の地面で跳ね返るようにしたいと思います。 そこで、ブロックするすべてのチャネルに衝突応答を設定します。 そのためには、weaponMesh->SetCollisionResponseToAllChannels と言うことができます。 衝突応答は ECollisionResponse::BLOCK になります。 したがって、完全にブロックするように設定されています。
ここで、ドロップしたら、ポーンを無視して、ポーンがそれをまたいで、衝突せずに通り抜けることができるようにします。 だから、weaponMesh->SetCollisionResponseToChannel と言って、その応答を ECollisionChannel に設定し、ポーンを選択します。 そして、その RESPONDS を ECollisionResponse::ignore に設定します。
もちろん、武器を落とすときはこれですべてですが、武器はその状態では開始されません。 そのまま歩いて持ち上げられる状態からスタートです。 そのため、最初から、weaponMesh の衝突を無効にしたいと考えています。 そのため、weaponMesh を取得し、setCollisionEnabled を ECollisionEnabled:: noCollision に呼び出すことでそれを行うことができます。
したがって、これらの衝突設定をそのまま維持できます。 そして、武器を実際に物と衝突させたい場合は、武器を落とすか投げるとします。次に、衝突を有効にして、物理のみを言うことができます。 またはAquarian Physicsまたはそのようなもの。
これで、areaSphere もできました。
エンジンのバージョンごとに変更される可能性のあるスケルタル メッシュ コンポーネント タイプを使用しても、エラーは発生しません。
そのため、インクルード エラーが発生した場合は、必ずそのヘッダーをインクルードしてください。
アクター クラスでこれを使用しなくても問題ありませんが、使用する sphereComponents を使用するには、sphereComponent ヘッダー ファイルをインクルードする必要があります。 それが [components/sphereComponent.h] にあることがわかっているので、それをインクルードして、areaSphere を作成します。 [areaSphere = createDefaultSubObject(USphere コンポーネント)] とします。 そして、これは単純にareaSphereという名前になります。
また、ルートにもareaSphereをアタッチしたいと思います。 [areaSphere->SetupAttachment(RootComponent)] ということになります。
さて、このエリアスフィアについて話しましょう。 この SPHERE は、CHARACTERS との重複を検出するために使用するものになります。 そしてそれらが重なり合ったら、武器を拾えるようにしたいと考えています。 ピックアップ ウィジェットのようなものを表示して、アイテムの状態などを設定できます。
しかし、[マルチプレイヤー ゲーム] と [マルチプレイヤー ゲーム内のシングル プレイヤー ゲーム] では、このタイプの違いがあります。 このような重要なことは、サーバー上でのみ実行することをお勧めします。
したがって、サーバー上にいる場合にのみ、areaSphere にオーバーラップ イベントを検出させたいと考えています。 したがって、areaSphere を取得して setCollisionResponseToAllChannels を呼び出したいと思います。 そして、ECollisionResponse::ignore を使用します。 そして、それはareaSphereが存在すらしないようなものです。
ここで、areaSphere とコンストラクターの衝突を無効にしてから、beginPlaying を実行したいと思います。 有効にしますが、サーバー上でのみ有効にします。
ここで、areaSphere->SetCollisionEnabled と言って ECollisionEnabled::NoCollision を渡します。 したがって、すべてのマシンで、これは衝突なしに設定されます。 しかし、サーバー マシンでは実際にコリジョンを有効にするように設定します。
先に進む前に、実際にはルートがないことに気付きました。 ルートをweaponMeshに設定します。 それでは、setRouteComponent を呼び出しましょう。 そしてweaponMeshを渡します。
サーバー上にいる場合は、衝突を有効にしたいと思います。 しかし、ここでコンストラクターでそれを行うのではなく、それを実行して beginPlay を開始します。 したがって、ここで権限があるかどうかを確認し、衝突を有効にすることができます。 後でオーバーラップ関数を追加するときに、それらをここにバインドして、サーバー上にある場合は beginPlay を実行できます。
ここで if チェックを入れます。 ここでできることは、getLocalRole を呼び出して、それが ENetRole::authority と等しいかどうかを確認することです。
その場合は、areaSphere で有効になっている衝突を呼び出すことができ、NoCollision の代わりに queryAndPhysics のようなものを使用できます。 また、オーバーラップさせたいチャネルに衝突応答を設定することもできます。これは、カプセルの衝突オブジェクト タイプであるため、ポーン衝突タイプになります。
そこで、areaSphere->setCollisionResponseToChannel と言います。 チャネルは ECollisionChannel になり、カプセルのコリジョン タイプであるポーン コリジョン タイプを選択します。 衝突応答は ECollisionResponse::Overlap になります。
だから私たちはこれを行うことができました。 しかし、私たちの役割が権威であるかどうかを確認する簡単な方法があります。 そして、それは hasAuthority 関数です。 これは同じことです。 ローカルの役割をチェックします。 そして、それが role [authority] と等しい場合、hasAuthority は True を返します。 これは、武器がレプリケート アクターである場合に当てはまります。 これは、サーバーがすべての武器オブジェクトを担当することを意味します。 したがって、私たちの武器はサーバー上でのみ権限を持ちます。 レプリケートするように設定する必要があり、コンストラクターでそれを行うことができます。 アクターには bReplicates ブール値があり、それを true に設定できます。
さて、このビデオを締めくくる前に最後に追加したいのは、武器の状態の列挙型です。 これを [weapon.h] のクラス宣言の直前に追加できます。
ここで、この列挙型の武器の状態を呼び出したいと思います。これはスコープ付きの列挙型になります。 つまり、EWeaponState という enum クラスを作成し、ここで uint8 を使用します。
したがって、enum 定数は符号なし 8 ビット整数であり、これもブループリント タイプになります。 そこで、blueprintType で UENUM を指定します。 そうすれば、この列挙型をブループリントの型として使用できます。
EWeaponsStates では、定数を列挙します。 EWeaponsState の前に EWS を付けます。
そして、初期状態が欲しいです。 これは、武器がワールドに置かれているときの状態です。 まだ拾ったことがなく、私たちのキャラクターは歩いて拾い上げて装備することができます.
EWS_initial 状態があり、これに UMETA マクロを指定して表示名を設定できます。これは表示名とブループリント用になります。 そして、これを【初期状態】と呼ぶことにします。
さて、イニシャルに加えて、実際に武器を装備したときの状態が欲しいです。 そこで、[装備] という別の列挙型定数を追加します。 その表示名は単に[装備]することができます。
そして、武器がドロップされたときの別の列挙型定数が必要です。 だから私はこれを[落とされた]と呼ぼう。 ここで、物理演算をオンにして、衝突をオンにして、武器を地面で跳ね返らせます。 だから私はこれに表示名を付けるつもりです[ドロップ]。
もちろん、ほとんどの enum 定数にはデフォルトの最大定数があり、これは [EWS_MAX] と呼ばれます。 そして、表示名 [default Max] を付けます。 そうすれば、この列挙型に実際に含まれる定数の数を知る必要がある場合は、EWS_Max の数値を確認できます。
よし、武器はこの武器状態列挙型を定義する。 このタイプの変数を武器クラスに追加してみましょう。 そして、これはプライベートでも構いません。 ここに貼り付けます。
EWeaponState、これをweaponStateと呼びます。 これを UProperty にします。 そして、BLUEPRINTS から見えるように、これを visibleAnywhere にします。
しかし、私はこの変数をゲーム ロジックから設定したいと考えており、それはほとんど C++ で行われます。 後でそれをブループリントに公開することに決めた場合は、公開できます。 しかし、実際には、そうする必要はありません。
これで、コードをコンパイルできます。
エディタに戻って、新しい武器クラスに基づいてブループリントを作成できます。 そこで、私の blueprints フォルダーに移動して新しいフォルダーを作成し、これを [weapon] と呼びます。 そして、weapon フォルダで右クリックし、[Blueprint クラス] を作成します。 ここですべてのクラスが展開されているので、weapon を検索して [Weapon C++ クラス] を選択し、それを選択します。 ここで、これを BP_weapon と呼び、これをダブルクリックします。 そして、これが私たちの武器クラスです。
これで、武器メッシュと areaSphere が表示されました。 これで、SKELETAL メッシュの横にあるドロップダウンをクリックして、すぐに武器メッシュを設定できるようになりました。 そして、「アサルトライフル」を選択するだけです。 今のところそれを使用します。
私のアサルトライフルがありますが、少しずれていることがわかります。 そこで、areaSphere を武器の中心まで少し移動します。 そして、球の半径を少しだけ大きくしてみようと思います。 そうすれば、かなり近くにいて BP_weapons self を選択しているときに、このことを拾うことができます。
[武器の状態] があり、[初期状態] である最初の列挙型定数に自動的に設定されます。
これで武器ができました。 それをコンパイルして保存します。 そして、ここで 1 つをレベルにドラッグしてみませんか。 そして今、私たちは武器を持っています。 現在、これに対する機能をプログラムしていないため、これと重複しても実際には何もしません。 しかし、それがゲームのクライアント インスタンスに存在し、サーバー上に武器が存在することはまだわかります。
この講義では、武器クラスを作成し、それにいくつかのコンポーネントを追加しました。また、現在の状態に応じて、コードの観点から武器をどのように扱うかを決定するために使用できる [weapons state] 列挙型も追加しました。
ここで、ポップアップするピックアップ ウィジェットを表示して、武器と重なるとすぐに武器を拾うことができることを知らせたいと思います。 これについては、今後の講義で扱います。
素晴らしい仕事。
また後で。
Welcome back.
Now, aside from our character, one of the more important classes in our game is going to be the weapon class. So we're going to create our weapon class. and this lecture, and we'll add some basic components that all weapons should have, as well as an enum for the weapon state. So we know how to treat the weapon. Depending on the state that it's in.
So let's get started. So we're going to need a weapon class. So I'm going to right click and add a [new C++ class]. And our weapon can simply be an ACTOR. So I'm going to choose ACTOR. Click next.
And I'd like to keep our weapon class and its own folder called [Weapon]. That Way later, when we derive more classes from Weapon. We can stick all those weapon classes in the weapon folder. Now, this class is going to be called [weapon]. So let's click [create class]. So we can hit no on this pop up message.
And here in Visual Studio, I have my weapon class. Now, I don't need the rest of these tabs open for now.
So I'm going to right click on[ Weapon.h] and select [close all but this]. and I can use [Ctrl + K or O], to open [weapon.cpp] from the weapon header file.
Now because weapon is in the weapon folder, we don't need this weapon part here as we've seen. So changing the include to just include [weapon.h] will fix all compiler errors.
So let's head over to our [weapon.h] file, where we have a constructor beginPlay and tick function. Now, just like I did with the CHARACTER class, I'm going to remove these comments as we don't really need them now.
And I'd like to add the basic components that all weapons should have. So I can make a [private section] here, for those component variables.
I'm going to go ahead and move TICK up here to the [public section] just under our Weapon constructor.
Now, in the [private section], I'd like a mesh for the weapon and all of the assets we have. If we go into our ASSETS folder and check out [militaryWeaponsSilver] and [weapons]. I see that these are all SKELETAL meshes. So my weapon class definitely needs a SKELETAL mesh component.
So let's add one of those. It's going to be a USkeletalMeshComponent, And I can call this weaponMesh.
Now, weaponMesh is getting a UProperty, of course, and I'm going to make in [visibleAnywhere]. And we'll be able to set the skeletal mesh on our component from blueprints. Now, I'll go ahead and give this a category, and call the category [weapon properties].
Now, in addition to a SKELETAL mesh, we're going to need some sort of overlap volume so that we can enable equipping this weapon when the character is close.
So I'm going to forward declare a USphereComponent and use a sphereComponent called areaSphere. And area sphere can get the same you property as weapon mesh.
Now we'll have more components as we develop this weapon. But for now, I think this is good. Let's go ahead and construct these and [weapon.cpp].
Now, the first thing I'm going to do before we construct these components is set bCanEverTick to false. If we decide later we need our weapon to tick, we can always change this. But I'm going to set it to false for now.
And I'm also going to remove these comments as they're not really helping us any.
we can construct our weaponMesh. I'm going to say weaponMesh = createDefaultSubObject and use USkeletalMeshComponent. And I'm going to call this weaponMesh.
So I'm going to say [weaponMesh->setupAttachment(rootComponent)].
Now later on, I plan on being able to drop this weapon, and I'd like the weapon to bounce off of the ground in the walls whenever we drop it. So I'm going to set its collision response to all channels to block. So to do that, I can say weaponMesh->SetCollisionResponseToAllChannels. And the collision response will be ECollisionResponse::BLOCK. So it's set to block at all.
Now, once we drop it, I would like to ignore the pawn so the pawn can step over it and run through it without colliding with it. So I'm going to say weaponMesh->SetCollisionResponseToChannel and I'm going to set its response to ECollisionChannel and I'm going to choose pawn. And set that RESPONDS to ECollisionResponse::ignore.
Now this is all, of course when we drop the weapon, but the weapon doesn't start off in that state. It's going to start off in a state where we can just walk up and pick it up. And so from the start, I'd like my weaponMesh to have its collision disabled. so I can do that by taking a weaponMesh and calling setCollisionEnabled to ECollisionEnabled:: noCollision.
So we can keep these collision settings as is. And once we want the weapon to actually start colliding with things, say we drop it or throw it. Then we can set its collision enabled to say physics only. or queryAndPhysics or something like that.
0 件のコメント:
コメントを投稿