

UEFNのVerse言語で関数の結果を指定する方法について教えてください!

初心者向けにわかりやすく解説してほしいですね!
こんなお悩みを解決します。
本記事の内容この記事を書いている僕は、金融系専門卒の投資家兼ブロガーです。実際にUEFNを使っており、現在進行形で学んでいます。
今回は、UEFNのVerseで関数の結果を指定する方法について解説していきます。
さっそく、やっていきましょう。

もくじ
結果の指定を学ぶまえに【前提】

関数はアクションを実行することができます。
また、関数を呼び出すことで特定の処理を実行し、その結果として値を返すこともあります。この返される値を「結果」と呼びます。
例えば、GetRandomInt(1, 10)
を呼び出すと、1から10までのランダムな整数を取得できることが期待されますね。
関数の戻り値の型を変更するには、関数シグネチャの型を変更します。
具体的な例は以下のとおり。
GetNumberOfMousetrapsYouCanAfford() : int
この場合、GetNumberOfMousetrapsYouCanAfford()
関数の戻り値の型が int
に設定されており、この関数を呼び出すと整数が返されることが期待されます。
GetNumberOfMousetrapsYouCanAfford() : float
逆に、戻り値の型を float に変更すると、異なる型の値が返されます。
関数の戻り値の型が指定されている場合、その関数の本体(コードブロック)では、その型に一致する結果を生成する必要があります。
もし結果を生成しない場合、コードはコンパイルエラーとなりますね。
これはつまり、関数が宣言された型の結果を返すことが要求されているということです。
以降では、この問題を回避する方法について学んでいきましょう。
結果と戻り値

結果とは、関数を実行した際にその関数から返される値を指します。
以前、「キーワード」について解説しました。
※キーワードは、プログラミング言語に組み込まれた特定の単語であり、それぞれが特定のアクションや処理に関連しています。
Verse では、return も、return キーワードの後に続く式から生成される値を結果として提供するよう関数に指示する キーワード です。
MyFunction() : int =
return 5
OnBegin<override>()<suspend> : void =
MyFunction() # result is 5
上記の例のコードでは、MyFunction()
が呼び出されたときに5
の値を返します。
return
キーワードを明示的に含めなくても、関数には問題が発生しませんが、return
を明確に指定することをおすすめします。
早期のreturn
プログラムにおいて、return
文が実行されると、その関数のコードブロックは即座に終了します。
つまり、return
文の後に続くコードは実行されません。
この機能は、特定の条件が満たされた場合に関数を早期に終了させる際に便利です。
以下の関数は、CoinsPerMouseTrap
に基づいてCoins
変数を更新します。
ただ、ネズミ捕り器を購入するためにはCoins
変数が正の値である必要があります。
もしCoins
が負の値である場合、関数はエラーメッセージを表示して戻り値を返します。
このような場合、関数の残りのコードを実行する必要はありません。
実際には、return
文を使用しない場合、この関数ではCoins
の値が誤って減少し、Coins
が負の値であることが示されません。
var Coins : int = -10
CoinsPerMousetrap : int = 100
BuyMousetrap() : void =
if (Coins < 0):
Print("Error: Coins set to negative value")
return
set Coins = Coins - CoinsPerMousetrap
Print(“Mousetrap bought! You have {Coins} coins left.”)
return
文を使用して関数を早期に終了する場合、コードの実行フローが予想外の結果となり、バグが発生する可能性があります。
具体的には、return
文がPrint(“Mousetrap bought!You have {Coins} coins left.”)
よりも前に実行されると、関数から抜ける前にCoinsの新しい値が出力されず、結果として意図しない挙動になります。
var Coins : int = 500
CoinsPerMousetrap : int = 100
BuyMousetrap() : void =
if (Coins < 0):
Print("Error: Coins set to negative value")
return
set Coins = Coins - CoinsPerMousetrap
return
Print(“Mousetrap bought! You have {Coins} coins left.”)
コードに早期のreturn
文が存在しても、通常はコンパイルは成功します。
しかし、Visual Studio Codeなどの統合開発環境では、return
文の後に続く式が実行されないことを警告として表示することがあります。
有益な結果のない関数のVoid
結果が必要な場合と必要ない場合があります。
レッスン2では、異なる型について学習しましたが、それぞれの型には特定の種類の値が必要であることも覚えているでしょうか。
以下は、簡単なリストですが、Verseでは多様な型が使用されます。
これらの型は、変数や定数を使用する際の基本的な要素となります。
型 | 動作 | 値 |
logic | True または False のいずれか | True / False |
int | 整数 | 整数値 |
float | 小数 | 小数点 |
string | テキスト(文字列) | 文字列、数字、句読点、スペース、絵文字 |
関数の戻り値が不要な場合、その関数の型を void
に設定することができます。
つまり、関数の型を void
にすることで、コードブロックの最後の式でどの型の結果でも生成せずに、コンパイルエラーを回避することができます。
void
型の関数では、return
キーワードを使用することも可能ですが、その際には値を提供する必要はありません。
練習問題

HurtPlayer()
関数は正常に動作していますが、現在は Damage()
メソッドに固定のリテラル値を渡しているため、その値を変更するにはコードを手動で変更する必要があります。
このレッスンでは、別の関数からの戻り値を使用して、HurtPlayer()
関数をより柔軟にする方法を学習します。
レッスン4では、プレイヤーの体力値に基づいて、条件式を使ってポーションのダメージや回復量を計算するコードの一部を取り上げました。
ここでは、その一部を CalculateDamage()
という関数に切り出し、この関数は float
型の値を返します。
この返り値を定数に格納し、それを後に Damage()
メソッドに渡すことで、HurtPlayer()
関数をより柔軟に操作することができます。
▼ まず、CalculateDamage
という名前の関数を作成します。
関数内で float 型の 2 つの定数 MinHealth
と PotionDamageAmount
、また、float 型の変数 PlayerHealth
も宣言しましょう。
# ダメージ計算に関する定数の宣言
CalculateDamage() : float =
# 最低限の体力値
MinHealth : float = 1.0
# ポーションのダメージ量
PotionDamageAmount: float = 80.0
# プレイヤーの体力値の変数宣言
var PlayerHealth : float = 100.0
▼ 3つの値の1つを返す if
… else if
… else
式を作成します。
PlayerHealth
がPotionDamageAmount
より大きい場合はPotionDamageAmount
PlayerHealth
がPotionDamageAmount
より小さくてMinHealth
より大きい場合はPlayerHealth
-MinHealth
PlayerHealth
がMinHealth
と同じ場合はPlayerHealth
# ダメージ量によってプレイヤーが倒れない場合は、そのダメージ量を実行します
if (PlayerHealth > PotionDamageAmount):
return PotionDamageAmount
else if (PlayerHealth > MinHealth):
# プレイヤーの体力値が低い場合は、もう一度チャンスを与えます
return PlayerHealth - MinHealth
else:
# プレイヤーを倒します
return PlayerHealth
上記は、CalculateDamage
関数内の一部で、プレイヤーの体力値に応じてダメージ量を計算するための条件式です。
まず、PlayerHealth
が PotionDamageAmount
よりも大きい場合、つまりプレイヤーの体力値がポーションのダメージ量よりも大きい場合、ポーションのダメージ量を戻り値として返します。
これにより、プレイヤーがポーションによるダメージで倒れないようになります。
次に、PlayerHealth
が PotionDamageAmount
よりも小さく、かつ MinHealth
よりも大きい場合、つまりプレイヤーの体力値がポーションのダメージ量未満であり、かつ最低限の体力値以上の場合、再度チャンスを与えるため、プレイヤーの体力値から最低限の体力値を引いた値を戻り値として返します。
最後に、上記の条件に当てはまらない場合、つまりプレイヤーの体力値がポーションのダメージ量以下であり、かつ最低限の体力値と同じかそれ以下の場合、プレイヤーは倒れたと判断し、現在の体力値をそのまま戻り値として返します。
return
は、関数内で計算された結果や値を返すために使用されるキーワードです。
関数が呼び出された場所に対して値を返す役割を果たします。

▼ 便利な結果を返す関数を作成したので、その結果を格納する必要があります。
DamageToDo
という名前の定数 float
を宣言し、CalculateDamage()
の戻り値で初期化します。
これを HurtPlayer()
関数に追加します。
HurtPlayer() : void =
Playspace : fort_playspace = GetPlayspace()
AllPlayers : []player = Playspace.GetPlayers()
if (FirstPlayer : player = AllPlayers[0]):
if (FortniteCharacter : fort_character = FirstPlayer.GetFortCharacter[]):
DamageToDo: float = CalculateDamage()
FortniteCharacter.Damage(50.0)
▼ 最後に結果を使用します。
DamageToDo
を引数として Damage()
に渡します。
CalculateDamage()
が返すものを正確に確認するために Print()
を追加します。
HurtPlayer() : void =
Playspace : fort_playspace = GetPlayspace()
AllPlayers : []player = Playspace.GetPlayers()
if (FirstPlayer : player = AllPlayers[0]):
if (FortniteCharacter : fort_character = FirstPlayer.GetFortCharacter[]):
DamageToDo: float = CalculateDamage()
Print("DamageToDo: {DamageToDo}")
FortniteCharacter.Damage(DamageToDo)
Damage()
メソッドを呼び出す際に、リテラル値ではなく CalculateDamage()
関数から返された値を使用しましょう。
CalculateDamage()
から返される値を使用することで、ダメージ量をプログラムの他の部分から制御可能にし、ゲームやアプリケーションの柔軟性と拡張性を高めることができるからです。
CalculateDamage()
メソッド内でダメージ量を計算するロジックを実装しています。
このメソッドを修正することで、ダメージの計算方法を容易に変更することができるわけですね。
例えば、プレイヤーのレベルやスキルに基づいてダメージを計算するように変更することができます。
これにより、ゲームのバランス調整や新しいルールの追加など、ダメージの計算方法を自由に調整できます。

まとめ

今回は、関数の結果を指定する方法について解説しました。
今回のまとめ- 結果とは、関数を呼び出した際に得られるもの
- コード ブロック 内では、最後の式が結果を生成する
- 関数から取得する値の型を変更するには、関数シグネチャ の型を変更する
- return は、その後に続く式から生成される値を提供するよう関数に指示するキーワード
- 早期 return は、ブロックが終了する前に return キーワードが使用されると発生する
- これにより、プログラムがコード ブロックをすぐに終了し、ブロック内の残りのコードが実行されることはない
- void は、関数の値が他のどの場所でも使用されることがないことを示す型である
- また、単に処理を実行する価値がないことを示す
- void は結果を生成する必要がない関数の型に使用できる
また、今回の演習で扱ったコードは以下のとおりです。
完全なスクリプトusing { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Fortnite.com/Playspaces }
using { /Verse.org/Simulation }
using { /Verse.org/Verse }
hello_world_device := class(creative_device):
# 実行中のゲームで仕掛けが開始されたときに実行します
OnBegin<override>()<suspends>:void=
HurtPlayer()
Print("Player Hurt")
CalculateDamage() : float =
MaxHealth : float = 100.0
MinHealth : float = 1.0
PotionDamageAmount: float = 80.0
var PlayerHealth : float = 100.0
# ダメージ量によってプレイヤーが倒れない場合は、そのダメージ量を実行します
if (PlayerHealth > PotionDamageAmount):
return PotionDamageAmount
else if (PlayerHealth > MinHealth):
# プレイヤーのヘルス値が低い場合は、もう一度チャンスを与えます
return PlayerHealth - MinHealth
else:
# プレイヤーを倒します
return PlayerHealth
HurtPlayer() : void =
Playspace: fort_playspace = GetPlayspace()
AllPlayers: []player = Playspace.GetPlayers()
if (FirstPlayer : player = AllPlayers[0]):
if (FortniteCharacter : fort_character = FirstPlayer.GetFortCharacter[]):
DamageToDo: float = CalculateDamage()
Print("DamageToDo: {DamageToDo}")
FortniteCharacter.Damage(DamageToDo)
次回は、入力、パラメータ、引数の仕組みについてやっていきます。
引き続き、がんばっていきましょう🔥
>> 【UEFNのVerse】関数でパラメータを定義して必要な結果を得る方法
-
-
【UEFNのVerse】関数でパラメータを定義して必要な結果を得る方法
続きを見る
※参考文献:Epic Games