いらっしゃいませ。
このレクチャーでは、クライアントにウィジェットを表示する方法と、これに変数の複製がどのように関係するかについて説明します。
ここで、変数がいつレプリケートされたかを知りたいと思います。 そのため、変数が複製されたときにクライアントで呼び出される関数を作成する方法を学びます。 このタイプの機能は REP 通知として知られています。
それでは始めましょう。
BlasterCharacter.h に戻り、現在オーバーラップしている武器を格納できる変数が必要です。 それでは、新しいプライベート変数を作成しましょう。 クラス AWeapon を前方宣言します。 この変数はoverlapingWeaponと呼ばれます。
ここで、この変数をレプリケートする必要があります。つまり、サーバーで変更されたときに、すべてのクライアントで変更する必要があります。 そして、武器へのポインターを複製できます。 これを行うには、UProperty を追加する必要があります。 ここで指定したレプリケートされた UProperty を追加します。
これにより、OverlapWeapon がレプリケートされた変数になるように指定されます。 さて、変数を複製するために必要なことはこれだけではありません。 パブリック関数になる関数をオーバーライドする必要があります。 したがって、ここの public セクションでオーバーライドします。
ここで、変数をレプリケートする予定のクラスでオーバーライドする必要がある関数は [virtual void] 関数であり、getLifetimeReplicatedProps と呼ばれます。
現在、この関数は FLifetimeProperties の TArray を取ります。 そして、この理論は参照によって渡され、outLifetimeProps と呼ばれます。
現在、この関数は [const] 関数です。そしてそれを 上書きする予定です。そして、この関数内で、レプリケートする変数を登録します。
それでは、getLifetimeReplicatedProps の関数定義を作成しましょう。 ここで、この関数定義を移動したいと思います。 頂上付近まで。 コンストラクタのすぐ下。 この関数を上書きしているので、super::getLifetimeReplicatedProps を呼び出す必要があります。 そのため、スーパー バージョンを呼び出して、その入力パラメーター outLifetimeProps を渡します。
[overlappingWeapon] 変数をレプリケートするために登録する必要があるのはここです。 これを行うには、doRepLifetime というマクロを使用します。 そして、doRepLifetime で ABlasterCharacter クラスを指定します。 これは、レプリケートされた変数を持つクラスです。 また、複製された変数も指定します。これは、overlapingWeapon になります。
doRepLifetime が定義されていないため、赤い波線が表示されることに注意してください。 そして、そのマクロは、変数をレプリケートするたびに含める必要があるヘッダーで定義されます。 インクルードするヘッダーは [net/unrealNetwork.h] です。 そのヘッダーを含めると、doRepLifetime が定義されます。 この変数は、初期化された時点で開始されます。 設定するまで null になります。
次に、武器クラスとオーバーラップ関数 onSphereOverlap から設定したいと思います。つまり、この変数のパブリック セッターが必要になるということです。 だから、ブラスターのキャラクターの一番下に 1 つ貼り付けます。
インラインにしたいので、forceInLine マクロを使用します。これは [VOID] になります。 これを setOverlappingWeapon と呼びます。
そして、AWeapon ポインターを受け取ります。 単純に【武器】と呼ぼう。 [overlappingWeapon = Weapon] を設定します。 したがって、この変数を設定できます。
そして、overlapingWeapon の値が変更されるとすぐに複製されます。つまり、すべてのクライアント (= blasterCharacters) で変数が設定されます。
現在、レプリケーションは変数が変更された場合にのみ機能します。 したがって、たとえば、すべてのフレームやすべてのネット更新を複製するわけではありません。 重複する武器がサーバー上で実際に変更された場合にのみ、クライアント上で変更されます。 [weapon.cpp] と onSphereOverlap でこれを設定できます。
では、ここで設定して、武器に onSphereOverlap を設定しましょう。 otherActor を BlasterCharacter にキャストしたので、ここでアクセスできる BlasterCharacter を取得します。 そして、ここ onSphereOverlap では、[this] を渡して setOverlappingWeapon を呼び出します。 したがって、武器はこの関数 (= setOverlappingWeapon) を呼び出します。 そして、私たちの blasterCharacter クラスでは [overlappingWeapon] が設定されます。
つまり、ピックアップ ウィジェットがここで有効かどうかを確認する必要がなくなりました。 つまり、BlasterCharacter にoverlapingWeapon を設定するだけです。 BlasterCharacter では、いつそのウィジェットを表示する必要があるかを知る必要があります。 そのウィジェットを表示するための便利な関数をここで武器クラスに作成したいと思います。
そこで [weapon.h] に公開セクションを追加します。 TICKのすぐ下。 こちらは【無効】となります。 これを showPickupWidget と呼びます。 これで、BShowWidget というブール値の入力パラメーターを与えることができます。 このようにして、ピックアップ ウィジェットを表示するか非表示にするかを true または false で渡すことができます。
それでは、showPickupWidget を定義しましょう。 ここにウィジェットを表示できます。 これからは武器を整理整頓しておきたいと思います。 だから私はTicKを動かすつもりです、ここでプレイ開始のすぐ下に。
showPickWidget では、pickupWidget->setVisibility を取得するだけです。 まず、pickupWidget が有効であることを確認します。 そうであれば、pickupWidget を取得し、bShowWidget を渡して setVisibility を呼び出します。 したがって、この関数を呼び出すときに渡したブーレンは、pickupWidget を表示するか非表示にするかを決定します。
問題は、いつこの関数を呼び出すかです。 我々は BlasterCharacter で OverlapWeapon が null であるかどうかを知っているだけであり、その情報を使用してウィジェットを表示または非表示にすることができます。
さて、このオーバーラップする武器変数が複製されたときに呼び出される関数があれば素晴らしいと思います。 しかし、私たちはまだそれを学んでいません。 したがって、あまり最適ではない単純なアプローチを取ることができますが、より良い解決策を学ぶまでは、今のところは機能します。
それでは、ティック関数に行きましょう。 繰り返しになりますが、これらを整理しておきたいと思います。 [BlasterCharacter.cpp]で。 そこで、TICK 関数を beginPlay のすぐ下に移動します。
ここでは、重複する武器が有効かどうかを確認するだけです。 もしそうなら、その重なっている武器にピックアップ ウィジェットを表示できることがわかります。
というわけで【if(OverlappingWeapon)】と言います。 それが有効であれば、overlapingWeapon を取得し、その showPickupWidget 関数を呼び出して True を渡します。
ここでは、overlapingWeapon を使用しています。つまり、そのヘッダー ファイルをインクルードする必要があります。 BlasterCharacter の上部に include を追加します。武器は Weapon クラスに含まれています。つまり、インクルードされた [blaster/Weapon/weapon.h] を追加する必要があります。 [weapon.h] をインクルードしているので、変数の型が定義されています。
ここ TICK では、overlapingWeapon がサーバーで設定されるとすぐに、すべてのクライアントでその pickupWidget を表示し、このブール値をフレームごとに true に設定します。 これもあまり最適ではありませんが、すぐにより良い方法を学びます。
これをコンパイルしてみましょう。 ここでエディターに戻り、これをプレイテストしてみましょう。 そして、これがどのように機能するかを見てください。
最初にクライアントの 1 つを制御しようとしていますが、ここでクライアントに pickupWidget が設定されていることがわかります。 実際、すべてのクライアントに設定されています。 これは、ここの tick 関数で、重複する武器がすべてのクライアントにレプリケートされるためです。 サーバー上で値が変更されるとすぐにこの変数がレプリケートされるように監視(mark)すると、レプリケートはこのように機能します。 その後、すべてのクライアントの BlasterCharacter のバージョンに設定されます。 この変数をここでレプリケートするように登録し、LifetimeReplicatedProps を取得します。
このキャラクターを所有しているクライアントにウィジェットを表示することだけが本当に意味があります。 クライアント マシンのシミュレートされたプロキシで武器をオーバーラップするように設定する必要はありません。 つまり、他の誰かが武器と重なっている場合、その武器の上にマシンのピックアップ ウィジェットを表示する必要はありません。
さて、私達はどのクライアントがこの変数をレプリケートするかを制御できます。これを行うには、この変数を複製するように登録するときに条件を追加して、複製条件を使用します。
別のマクロを使用します。 DOREPLIFETIME_CONDITION を使用します。 クラスと変数を指定するだけでなく、条件も指定します。 現在、条件を指定するために使用できる列挙定数があります。
[自律のみ] という条件があることに注意してください。 これは、これを [自律プロキシ] に複製するだけです。
[所有者のみ] など、他にもいくつかあります。 ここで、所有権の概念について詳しく説明しますが、ポッドを制御しているのは誰でもあると考えてください。 マシンでポーンを制御している場合は、そのポッドの所有者です。 したがって、所有者のみを条件として指定すると、重複する武器は BlasterCharacter を所有するクライアントにのみ複製されます。
それでは、これをコンパイルして、ここでの動作を見てみましょう。 再生ボタンを押して、クライアントの 1 つで武器に近づきます。
ここで違いがあることに注意してください。 サーバー上では確認できますが、クライアントではこの pickupWidget のみが表示され、他のクライアントでは武器と重なって表示されますが、ここでは表示されません。 これは、変数がこのクライアントに複製されなかったためです。 武器の areaSphere とオーバーラップするポーンを所有するクライアントにのみ複製されます。
ここで、武器の onSphereOverlap で、overlapingWeapon を設定していることに注意してください。 そして、これはサーバー上でのみ発生します。 そのため、私達がsetOverlappingWeapon を呼び出すとすぐに、BlasterCharacter のここで、サーバー上に OverlappingWeapon を設定します。
サーバーに設定しているので、所有しているクライアントに複製しています。 getLifetimeReplicatedProps で指定しているように、所有者に複製するためだけです。
サーバーがオーバーラップしているポーンを制御していない限り、サーバー上で pickupWidget を確認する必要はありません。 つまり、そのポーンを所有しています。
したがって、 tick 関数で pickupWidget を表示するこの方法は機能しません。 削除する tick 関数で pickupWidget の可視性を設定する代わりに、変数の値が複製されるたびに呼び出される関数を設定できます。
このタイプの機能は、[rep notify] と呼ばれます。 設定方法は次のとおりです。 こちらと【BlasterCharacter.h】。 [rep notify] となる関数を作成できます。
これらは void 関数であり、規則では OnRep アンダースコアを使用し、その後に [レプリケートされる変数の名前] を続けます。 これは [overlappingWeapon] になります。 [rep notify] に意味のある値を渡すことはできません。これは、変数が複製されるときに自動的に呼び出されるためです。 これらも UFunction である必要があるため、これを使用するには UFunction マクロが必要です。
ここで、この [rep notify] を指定するために、overlapingWeapon がレプリケートされるたびに呼び出されるように、overlapingWeapon UProperty を取得し、[replicatedUsing] の指定を追加してから、[rep notify] を指定します。 つまり、OnRep_overlappingWeapon になります。 この UProperty を使用して、overlappingWeapon がそのクライアントにレプリケートされるときに、クライアントで onRep_OverlappingWeapon が呼び出されるように指定します。
では、この [REP notify] の定義を作成しましょう。 これが [REP 通知] です。 [rep notify] では、複製されたばかりなので、overlapingWeapon が変更されたことがわかります。 ここで pickupWidget を表示できます。
まず、overlapingWeapon が null でないかどうかを確認する必要があります。 null になる可能性があるためです。 OverlapingWeapon が以前は null ではなかったときにサーバーから null に設定されている場合、その変更はクライアントに複製されます。 したがって、OverlapWeapon が有効な場合、OverlapWeapon を取得して showPickupWidget を呼び出し、True を渡すことができます。
それでは、これをコンパイルして、これがどのように機能するかを見てみましょう。 というわけでプレイを叩きます。
そして今、クライアントと重なって、ここで何かに気付く。 武器と重なったクライアントのウィジェットのみが表示されます。 ここのサーバーには表示されません。 さて、これは注目すべき重要な詳細です。 [rep notifications] がサーバー上で呼び出されないため、サーバー上でウィジェットを取得しません。 それらは、変数が複製され、複製がサーバーからクライアントへの一方向でのみ機能する場合にのみ呼び出されます。 したがって、サーバーに複製されることはないため、サーバーは [rep notify] を呼び出すことはありません。
したがって、ここでサーバー上の武器とサーバーが制御するキャラクターとオーバーラップすると、別の問題が発生します。 ウィジェットを取得できません。これは、担当者通知でそのウィジェットのみを表示しているためです。 そのため、サーバー側でケースを処理する必要があります。
では、overlapingWeapon を設定する関数でこれを処理しましょう。 単純な getter ではなく、FORCEINLINE を削除し、この setter にさらにロジックを追加します。 したがって、このようにすべてを 1 行で定義するつもりはありません。
重複する武器と[blasterCharacter.cpp]のセットを定義します。 [rep notify] のすぐ上に設定します。 このセッターで最初に行うことは、setOverlappingWeapon です。 したがって、それを武器と同じに設定します。
次に、実際にポーンを制御しているキャラクターにのみウィジェットを表示するようにする必要があります。 これで、これがサーバー上でのみ呼び出されることがわかりました。 サーバー上でのみ呼び出される武器の onSphereOverlap から呼び出しているためです。
しかしここで、ポーンを制御しているキャラクターに実際に乗っているかどうかを知る必要があります。 isLocallyControlled というブール値を返す非常に便利な関数で確認できます。 isLocallyControlled は、実際に制御されているキャラクターでこの関数が呼び出された場合に true になります。
繰り返しますが、私たちはサーバー上にいることを知っています。 したがって、この if チェックの内部に到達すると、サーバー上でゲームをホストしているプレイヤーによって制御されているキャラクターにいることがわかります。 その場合、ここには所有者のみの条件があるため、overlapingWeapon が複製されないことがわかります。 また、このキャラクターはサーバー上でローカルに制御されるため、どのクライアントもこのキャラクターの所有者にはなりません。 したがって、この場合は、pickupWidget を表示するだけです。
ここでこのロジックを使用して、ここの if ステートメントに貼り付けます。 これで、サーバー制御のキャラクターがウィジェットとオーバーラップすると、サーバー上にウィジェットが表示されることがわかりました。
それでは、これをコンパイルしましょう。 エディターで、これをテストできます。
というわけで、ここに自分の【サーバー操作キャラ】を乗せて重ねていきます。 そして今、pickupWidget があることがわかります。 2 つのクライアントをここに戻すと、クライアントにウィジェットが表示されないことがわかります。
これはまさに私が欲しかったものです。なぜなら、キャラクターをコントロールしているプレイヤーのために、マシン上でその pickupWidget だけを見たいからです。
クライアント上でオーバーラップすると、ピックアップ ウィジェットが表示されます。 クライアントのみがオーバーラップし、サーバーはオーバーラップしない場合をテストできます。 したがって、クライアントとオーバーラップしても、サーバーには表示されません。
だから私たちは近づいています。 オーバーラップを停止しても、ウィジェットはまだ非表示になっていません。 ウィジェットはまだあります。 つまり、[オーバーラップの終了] 関数が必要です。
それでは、それを追加しましょう。 [wepon.h] でそれを行うことができます。 したがって、onSphereOverlap に加えて、[onSphereEndOverlap] が必要です。 [void onSphereEndOverlap] になるようにしましょう。
そして、このタイプのオン コンポーネント [オーバーラップ デリゲートの終了] のコールバックの場合。 [overlapComponent と呼ばれる UPrimitiveComponent]、[otherActor と呼ばれる AActor]、[otherComp と呼ばれる UPrimitiveComponent]、および [int32 otherBodyIndex] が必要です。
そこで、これらの入力パラメータをここに追加します。 また、これには UFunction マクロも必要です。 だから私はそれを追加するつもりです。 そして、この関数を定義できます。
[weapons.cpp] では、sphereOverlap で行ったのと同じことを行います。つまり、otherActor を取得して blasterCharacter にキャストします。 その blasterCharacter が有効な場合は、setOverlapping を呼び出します。 オーバーラップを終了しているので、これに設定する必要はありませんが、null に設定しています。 ここではヌルポインタを使います。
したがって、オーバーラップを終了すると、キャラクターの OverlapingWeapon は null になります。 そのため、そのウィジェットを非表示にする方法を知る必要があります。 null に設定しているためです。 したがって、null ポインターにアクセスして showPickupWidget を呼び出すことはできません。
さて、Blaster キャラクターに戻り、OnRep_overlappingWeapon を見てみましょう。 これがrepNotifyです。
ここで、入力パラメーターを渡すことができないと述べました。これは、onRepOverlappingWeapon をアクティブに呼び出していないためです。 変数がレプリケートされると自動的に呼び出されますね。
では、武器を NULL に設定した後で、重複する武器にアクセスするにはどうすればよいでしょうか? ここでも単純なアプローチは、lastOverlappingWeapon などと呼ばれる武器ポインター型の別の変数を作成することです。 また、重複する武器を変更する前にポインタを保存できます。
しかし、もっと簡単な方法があります。 おわかりのように、rep 通知には入力パラメーターを含めることができますが、レプリケートされる変数の型の入力パラメーターしか含めることができません。 つまり、onRep_overlappingWeapon は AWeapon ポインターのみを持つことができます。 これを lastWeapon と呼びます。
これは、repNotify に入力パラメーターを追加すると、変数のレプリケーションで呼び出されたときに何が渡されるのでしょうか? 複製が行われる前の最後の値になります。
つまり、オーバーラップする武器が NULL から始まるとしましょう。これは事実ですよね? サーバー上で変更されるとすぐに、新しい値がクライアントに複製されます。 ここに武器の入力パラメータがある場合、この関数内の lastWeapon の値は、変数が複製される前のOverlapWeaponの最後の値になります。
つまり、null の場合もあれば、設定前にオーバーラップしていた LastWeapon の場合もあります。 そのため、武器の変更が重複している場合は、変更前の最後の値を確認する必要があります。これには、lastWeapon を使用してアクセスできます。
その値が null でない場合、最後の武器にアクセスしてピックアップ ウィジェットを非表示にすることができます。 では、ここでそれを行います。
[if(lastWeapon.)]... とします。lastWeapon が null でない場合は、lastWeapon を取得して ShowPickupWidget を呼び出し、False を渡します。
このように、オーバーラップを終了すると、overlapingWeapon は null に設定されます。つまり、これはもちろん、チェックが失敗することを意味しますが、overlapingWeapon の最後の値には、オーバーラップを停止した武器へのポインターがまだ含まれています。 その場合、ピックアップ ウィジェットを非表示にすることができます。
これをコンパイルしてテストする前に、このコールバック onSphereEndOverlap を作成しました。 これを end コンポーネントにバインドし、areaSphere のデリゲートをオーバーラップする必要があります。
[weapon.cpp] で。 ここでこれを行うことができ、チェック hasAuthority で beginPlay を実行できるため、これがサーバー上でのみ発生するようにします。
そこで、areaSphere を使用して onComponentEndOverlap と addDynamic を使用し、[this] を AWeapon::OnSphereEndOverlap と共に使用します。
これで、AWeapon とのオーバーラップを停止すると、onSphereEndOverlap が呼び出されることがわかりました。
それでは、これをコンパイルしましょう。 そして、これをテストします。
私のクライアントの1人を連れて行くことで、私は重なります。 その pickupWidget があります。今、オーバーラップを終了し、pickupWidget は消えます。 OverlapWeapon が null に設定されていても、その値 lastWeapon は null ではないためです。 最後の値があるので、それにアクセスしてウィジェットを非表示にします。 したがって、これは両方のクライアントで機能します。 ここに私の他のクライアントがあり、ここで機能していることがわかります。
しかし、サーバーを使用してオーバーラップを終了すると、機能しません。 これは、repNotify でのみこれを設定しており、repNotify がサーバー上で呼び出されないためです。 したがって、私たちがサーバーである場合は、[ケース] を処理する必要があります。
BlasterCharacter でこれを行うことができます。 setOverlappingWeapon のセッターです。 ここで、overlapingWeapon の値を実際に設定しています。 したがって、この値を設定する前に、重複する武器が有効かどうかを確認し、pickupWidget を変更する前に非表示にすることができます。
したがって、重複する武器が有効かどうかを確認するこれらの行を使用して showPickupWidget を呼び出すと、ここで false を渡すことができます。
これをコンパイルして、これをテストしてサーバー上で再生し、pickupWidget と onEndOverlap を取得します。 ウィジェットを非表示にします。 これはまだクライアントで機能します。 そのクライアントがいて、これが私の別のクライアントです。 そのため、pickupWidget を表示して適切なタイミングで非表示にし、正しいプレーヤーに対して表示しています。
さて、ここでローカルに制御されているかどうかを確認せず、OverlappingWeapon を設定しても問題ありません。 考えてみると、これはサーバーでのみ呼び出されるため、そのオーバーラップ関数で呼び出されます。
また、サーバー上で何かとオーバーラップしている場合、ローカルで制御されているオーバーラップしているキャラクターのみがウィジェットを表示する必要があるため、サーバー上で他のキャラクターの pickupWidget を実際に表示する必要はありません。
これで、必要な動作が得られました。
この講義では、変数の複製について学び、overlapingWeapon という AWeapon へのポインタを複製しています。
また、レプリケーションはサーバーからクライアントへの一方向にしか機能しないことがわかりました。
また、[rep notifications] についても学びました。これは、変数が複製されるときに呼び出される関数です。
また、サーバーからのみ変数がサーバーにレプリケートされることはないため、repNotify はクライアントでのみ呼び出されることがわかりました。
そして、条件を使用して、キャラクターの所有者にのみ複製できるようにする方法を学びました。
したがって、変数値をすべてのクライアントにレプリケートするのではなく、現在 Pawn を制御しているクライアントにのみレプリケートします。
私たちの(場合)BlasterCharacter.
よくやった。
次回の講義に続きます。