主なコンテンツ

〜主なコンテンツ〜

1. Unityで製作したゲームと製作Tips
  1. 三月精チャレンジ(東方Project二次創作)
    1. 作り方
  2. 英語学習2D(オリジナルスマホアプリ)
2. UE4
3. ゲームアプリ見学
4. Bitbucket & SourceTreeでの一連の流れ
  1. 前半
  2. 後半
5. Tips
  1. UnityのTips
  5. SQL文のTips
  6. Final IK
  7. GearVR+Unity

2023年3月19日日曜日

46. Pickup Widget

 おかえり。


この講義では、武器クラスのピックアップ ウィジェットを作成します。 これにより、武器をピックアップできることがわかり、武器の状態に基づいて、このピックアップ ウィジェットの可視性をいつ設定するかを決定します。


HUD フォルダに移動し、右クリックして [User Interface] に移動し、[Widget Blueprint] を選択します。 これを WBP_pickup_widget と呼びます。


このウィジェットはシンプルです。 武器を拾うことができることを伝えるテキストが表示されるだけです。


[キャンバス パネル] を削除し、[テキスト ブロック] を追加します。この [テキスト ブロック] は、pickupText と呼ぶことができます。 テキストは「E-pickup」に設定します。 これにより、E キーを使用して武器を拾うことができることがわかります。


ここで、サイズを少し大きくして、たとえば約 48 にして、テキスト ウィジェットのサイズを変更します。 そして、書体をボールドからレギュラーに変更し、[位置揃え] を中央に設定したいと思います。


これで、コンパイルして保存できます。 ここで、ウィジェット コンポーネントを武器クラスに追加したいと思います。 [weapon.h] に、ピックアップ ウィジェット用のプライベート変数を追加します。 そこで、UWidgetComponent ポインターを前方宣言し、これを pickupWidget と呼びます。


次に、どこでも編集できるようにし、カテゴリ [武器のプロパティ] を指定します。 そして、これらの他の変数には [武器のプロパティ] がカテゴリとして含まれているため、そのカテゴリを WeaponState にも指定します。

あとは、このコンポーネントと [weapon.cpp] を作成するだけです。


コンストラクターの一番下までスクロールして、pickupWidget とします。 これを createDefaultSubObject で作成します。

さて、これは UWidgetComponent です。 そして、これを pickupWidget と呼びます。 これをルートにアタッチできます。 [pickupWidget->setupAttachment(rootComponent)] とします。


そしてもちろん、ウィジェット コンポーネントのインクルードを追加する必要があります。 この上部に、[components/widgetComponent.h] になるインクルードを追加します。


ウィジェットを作成したので、コンパイルしてエディターに戻り、武器フォルダーに移動して BP_weapon を開きます。 BP_weapon には、pickupWidget があり、[スペース] を [スクリーン] スペースに設定し、[ウィジェット クラス] を選択します。 BP_pickup_widgetになり、[希望のサイズで描画]にチェックを入れます。


ビューポートで、pickupWidget を上に移動し、weaponMesh のすぐ上にあることを確認します。 これでコンパイルできます。


再生ボタンを押すと、pickupWidget が武器の上にないように見えます。 原点はきっとあそこにある。 そのため、rootComponent が設定されていることを確認します。 これにはweaponMeshを選択します。 そこで setRouteComponent として、weaponMesh を使用します。 そのため、pickupWidget はかなり良さそうです。

次に、いつウィジェットを表示し、いつウィジェットを非表示にするかを決定する必要があります。 そしてそのエリアスフィアにキャラクターが重なったらすぐに見せたいです。


また、プレーヤーの役割を表示するために、このオーバーヘッド ウィジェットはもう必要ありません。 後でキャラクターの上にプレイヤー名などを表示するために使用できるので、オーバーヘッド ウィジェットは残しておきます。 そのため、ウィジェットを CHARACTER クラスから削除するのではなく、オーバーヘッド ウィジェット BLUEPRINT に移動して、テキスト ブロックを取得し、そのテキストを空の文字列に設定することができます。


さて、ウィジェットを表示したりウィジェットを非表示にしたりできるように、areaSphere のオーバーラップ イベントを設定する必要があります。 これは、オーバーラップ関数が必要であることを意味します。 これを[保護されたセクション]に追加します。


そうすれば、必要に応じてそれと子クラスをオーバーライドできます。 仮想関数を作成します. これは VOID になります. これを単に OnSphereOverlap と呼びます.


以前にオーバーラップ関数を作成し、コンポーネント beginOverlap のコンポーネントにバインドしたことがある場合、この関数には特定の署名が必要であることがわかります。


最初の入力パラメーターは、overlappedComponent と呼ばれる UPrimitiveComponent である必要があります。


次に、OtherActor という AActor があり、その後に otherComp という別のプリミティブ コンポーネントが続きます。


そして、otherBodyIndex という名前の int32 があります。


次は bFromSweep という bool です。


最後に、const FHitResult があります。これは、sweepResult と呼ばれる const 参照です。


そして、これらの入力パラメーターが必要な情報をどこで見つけることができるかを簡単に説明できます。


これをコンポーネントの開始オーバーラップのデリゲートにバインドします。 したがって、それは UFunction でなければなりません。 したがって、この関数の定義を作成できます。 それを定義する前に、areaSphere のオーバーラップを開始するコンポーネントにバインドしたいと思います。


繰り返しますが、サーバー上でオーバーラップ イベントが発生することだけを望んでいるので、if has authority チェック内でこのオーバーラップ関数を実際にバインドできます。 したがって、areaSphere を取得して OnComponentBeginOverlap にアクセスし、addDynamic を使用できます。 最初の入力はユーザー オブジェクトで、2 番目の入力はコールバック関数です。 そこで、オペレーターのアドレスを使用します。

関数は AWeapon::onSphereOverlap です。


今。 これらの入力パラメーターを見つける方法を簡単に説明すると約束しましたが、これはコンポーネントの beginOverlap を調べることで実行できます。


定義を見てみましょう。これは FComponentBeganOverlapSignature 型のデリゲートであることがわかります。 この定義をピークにすると、[primitiveComponent.h] で、declare_dynamic_multicast_sparse_delegate_six_params を使用してこのデリゲートが作成されていることがわかります。


ここにデリゲート型名が表示され、その後に入力パラメーターのリストが続きます。 そして、このマクロは、これらの入力パラメーターを持つ関数用に設計されたデリゲートを構築します。 このようにして、このタイプのデリゲートにバインドできるようにするには、オーバーラップ関数にこれらの入力パラメーターが必要であることがわかります。


onSphereOverlap 関数をバインドしていますが、[権限] を持つ武器のサーバーでのみ実行しています。 これを行っているので、onSphereOverlap 関数で、ピックアップ ウィジェットの可視性を設定するなどの操作を行うことができます。


ここで、他のアクターが blasterCharacter である場合にのみ可視性を設定したいと考えています。 そこで、BlasterCharacter のヘッダー ファイルをインクルードします。 これが [blaster/character/blasterCharacter.h] になります。


これをインクルードしたので、otherActor を blasterCharacter にキャストできます。 だから私は「ABlasterCharacter、そして単にこれを BlasterCharacter と呼びます。ABlasterCharacter にキャストします」と言うことができます。


そして、私はotherActorをキャストしています。 したがって、BlasterCharacter が有効である場合、キャストは成功し、BlasterCharacter は areaSphere とオーバーラップしています。 その場合は、pickupWidget の可視性を設定できます。 それでは、pickupWidget を取得して setVisibility を呼び出し、true を渡しましょう。


今、pickupWidget にアクセスしています。 したがって、それが null ポインターでないことも確認する必要があります。 そのため、if ステートメントに追加して追加し、これらの両方を同時にチェックしてみましょう。


ここで、この pickupWidget の可視性を最初から false にしたいと思います。 そこで、beginPlay に移動して、pickupWidget が有効かどうかを確認するチェックを追加し、有効な場合は可視性を false に設定します。


それでは、コンパイルしてみましょう。 これをテストするとどうなるか見てみましょう。


まず、サーバー制御のキャラクターで武器に近づきます。ピックアップ ウィジェットが表示されます。


さて、クライアントに表示される内容を見てみましょう。 ピックアップ ウィジェットは表示されません。 そして、これが私の他のクライアントで、ピックアップウィジェットが表示されません。 そして、クライアント上で重なっても、クライアント上ではまだ見えません。


クライアントが武器とオーバーラップした場合、サーバーで何が起こるか見てみましょう。 私はクライアントでオーバーラップするつもりで、サーバーでそれを確認します。 ピックアップ ウィジェットが表示されるようになりました。 これは、サーバー上でオーバーラップ イベントのみを生成しているためです。 また、オーバーラップ イベントが発生した場合は、可視性を設定し、サーバー上でのみ呼び出される sphereOverlap を設定します。


これまでのところ、すべてが期待どおりに機能しています。 ただし、クライアントの可視性も設定する必要があります。


サーバーがウィジェットの可視性を表示することを制御する権限の部分があります。 その後、キャラクターが武器を拾えるようにします。 ただし、ウィジェットが重なっている場合は、クライアントにウィジェットを表示していません。 そのため、それを行う方法を理解する必要があります。 これにはレプリケーションが含まれますが、これについては次に説明します。


このレクチャーでは、ピックアップ ウィジェットを武器クラスに追加し、オーバーラップ関数を作成して、areaSphere のオーバーラップを開始するコンポーネントにバインドしました。 ただし、サーバー上でのみ行いました。


したがって、サーバーは、ピックアップ ウィジェットを表示できるかどうか、および講義が来るかどうかを制御できます。 サーバーからクライアントに変数をレプリケートする作業を行って、ピックアップ ウィジェットの可視性をいつ設定するかをクライアントが認識できるようにします。 これで、ウィジェットのテキストが画面に表示されます。


素晴らしい仕事。


また後で。


Welcome back.


In this lecture, we're going to make a pick up widget for our weapon class. And this will allow us to know that we can pick the weapon up and then we'll decide when we should set the visibility for this pickup widget based on the weapon state.


So I'm going to go into my HUD folder and right click and go to [User Interface] and Select [Widget Blueprint]. And I'm going to call this WBP_pickup_widget.


this widget will be simple. It's just going to have some text that will tell us that we can pick the weapon up.


So I'm going to remove the [canvas panel] and simply add a [text block], and this [text block] can be called pickupText. Now for the text, I'm going to set this to" E - pickup". and this will let us know that we can use the E key to pick up the weapon.


Now we can increase the size a bit, say to about 48 and resize the text widget. And I'm going to change typeface from bold to regular and I'd like to set the [justification] to center.


Now I can compile and save. Now I'd like to add a widget component to the weapon class. So here in [weapon.h], I'm going to add a private variable for the pickup widget. So I'm going to forward declare a UWidgetComponent pointer and call this pickupWidget.


Now I'm going to make it edit anywhere and give it the category [weapon properties]. And since these other variables have [weapon properties] as the category, I'm going to give that category to weaponState as well.

Now I just need to construct this component and [weapon.cpp].


So I'm going to scroll down to the bottom of the constructor and say, pickupWidget. And I'm going to create this with createDefaultSubObject.

Now, this is a UWidgetComponent. And I'll just call this pickupWidget. and I can attach this to the root. So I'm going to say [pickupWidget->setupAttachment(rootComponent)].


And of course, I need to add the include for widget component. So up here at the top, I'm going to add the include it's going to be an [components/widgetComponent.h].


so I've constructed the widget let's compile and back in the editor I can go to my weapon folder and open BP_weapon. Now here in BP_weapon, I have my pickupWidget and I'm just going to set the [space] to [screen] space and select the [widget class]. It's going to be BP_pickup_widget and I'm going to check [draw a desired size].


Now here in the viewport, I'm going to move the pickupWidget up and make sure it's right above the weaponMesh. Now I can compile.


now if I hit play, the pickupWidget looks like it's not above the weapon. It's probably over there at the origin. So I'm going to make sure I have a rootComponent set. and I'm going to choose the weaponMesh for this. So I'm going to say setRouteComponent and use weaponMesh. So the pickupWidget looks pretty good.

Now we need to decide when to show the widget and when to hide the widget. And I'd like to show it as soon as the character overlaps with that areaSphere.


And I also don't really need this overhead widget to show the player role anymore. Now I'm going to keep the overhead widget because we can use it later to display things like the player name above the character. So rather than remove the widget from the CHARACTER class, I can just go into my overhead widget BLUEPRINT and take the text block and set its text to an empty string.


Okay, so we need to set up an overlap event for our areaSphere so that we can show the widget and hide the widget. So this means that we need an overlap function. Now I'm going to add this to the [protected section].


That way we can override it and child classes if we need to. So I'm going to make a virtual function, It's going to be VOID, And I'll simply call this OnSphereOverlap.


Now, if you've made overlap functions before and bound them to a components on component beginOverlap, then you know that this function has to have a specific signature.


The first input parameter needs to be a UPrimitiveComponent called overlappedComponent.


Next, we have an AActor called OtherActor, followed by another you primitiveComponent called otherComp.


And then we have int32 called otherBodyIndex.


Next is a bool called bFromSweep.


And last, we have a const FHitResult and that's a const reference called sweepResult.


And I can briefly show you where you can find that information what these input parameters need to be.


Now we're binding this to a delegate on component begin overlap. So it has to be a UFunction. So I can make a definition for this function. And before I define it, I'd like to bind it to on component begin overlap for the areaSphere.


And again, I really only want overlap events to happen on the server so I can actually bind this overlap function inside my if has authority check. So I can take my areaSphere and access OnComponentBeginOverlap and use addDynamic. And the first input is the user object and the second is the callback function. So we're going to use the address of operator.

And the function is AWeapon::onSphereOverlap.


Now. I promised I would show you briefly how to find these input parameters and that can be done by taking a look at on component beginOverlap. 


So let's peek the definition and we see that this is a delegate with the type FComponentBeganOverlapSignature. and if we peak the definition for this, then here in [primitiveComponent.h] we see that declare_dynamic_multicast_sparse_delegate_six_params was used to create this delegate.


Now we see the delegate type name here, followed by the list of input parameters. And this macro constructs a delegate designed for functions that have these input parameters. And so that's how I know that my overlap function has to have these input parameters to be able to bind to a delegate of this type. 


we're binding our onSphereOverlap function, but we're only doing it on the server for weapons that have [authority]. And now that we're doing this, we can do something in our onSphereOverlap function such as setting the visibility for the pickup widget.


Now I only want to set the visibility if the other actor is a blasterCharacter. So I'm going to include the header file for BlasterCharacter. Now that's going to be an [blaster/character/blasterCharacter.h].


So now that I have this include, I can cast otherActor to a blasterCharacter. so I can say "ABlasterCharacter, and simply call this BlasterCharacter. Cast to ABlasterCharacter".


And I'm casting otherActor. So if BlasterCharacter Is valid that our cast succeeded and a BlasterCharacter has overlapped with the areaSphere. So if that's the case, we can set the visibility for pickupWidget. So let's get pickupWidget and call setVisibility and pass in true.


Now we're accessing pickupWidget. So we should also make sure that that is not a null pointer. So let's add in and into the if statement and check both of these at the same time.


Now, I'd like this pickupWidget to have a visibility of false from the start. So I'm going to go up to beginPlay and add a check to see if pickupWidget is valid and if so, set the visibility to false.


So let's compile now. Let's see what happens when we test this out.


Now first, I'm going to run up on to the weapon with my server controlled character and I see that I get the pickup widget.


Well, let's take a look at what we see on the client. We don't see the pickup widget. And here's my other client and I don't see the pickup widget there. And even if I overlap on the client, I still don't see it on the client.


Now let's see what happens on the server if a client overlaps with the weapon. I'm going to overlap on a client and we see that on the server. The pickup widget has become visible. And this is what we should expect because we're only generating overlap events on the server. And if an overlap event occurs, we're setting the visibility and on sphereOverlap, which is only called on the server. 


So thus far, everything is working as expected. But we do need to make sure that we take care of setting the visibility on clients as well.


we've got the authority part down where the server is in control of showing the visibility of the widget. and later on enabling the character to pick up a weapon. But we're not showing the widget on the clients when they overlap with it. So we need to figure out how to do that. And that is going to involve replication, which we're going to cover next.


So in this lecture, we added a pickup widget to our weapon class and we created an overlap function and bounded to on component begin overlap for our areaSphere. But we only did so on the server.


So the server has control over whether or not the pickup widget can be seen and the lectures to come. We're going to work on replicating variables from the server to the client so the client knows when it's time to set that visibility for the pickup widget. So we can see that widget text on the screen.


Awesome job.


I'll see you soon.

0 件のコメント:

コメントを投稿