UEFN Verse言語 メタバース

【UEFNのVerse】関数でパラメータを定義して必要な結果を得る方法

【UEFNのVerse】関数でパラメータを定義して必要な結果を得る方法
みなみ

関数でパラメータを定義して必要な結果を得る方法について教えてください!

りゅう

初心者向けにわかりやすく解説してほしいですね!

こんなお悩みを解決します。

 本記事の内容
 本記事の信頼性

この記事を書いている僕は、金融系専門卒の投資家兼ブロガーです。実際にUEFNを使っており、現在進行形で学んでいます。

今回は、関数でパラメータを定義して必要な結果を得る方法について解説していきます。

さっそく、やっていきましょう。

あすか

前回は・・・

UEFN Verse 前回は

入力は、プログラム内で使用するために情報を追加したり変更したりするためのデータや値のことを指します。

前回の解説「関数の結果を指定」では、入力の必要はありませんでした。

GetNumberOfMousetrapsYouCanAfford() : int

上記のとおり、関数シグネチャの()が空であることがわかりますね。

パラメータ

パラメータ

関数が必要とする 入力 は、関数シグネチャにパラメータ(引数)を追加して定義することができます。

※関数シグネチャは、括弧内に宣言される定数のこと。関数の名前、戻り値の型、およびパラメータの型を指します。

※パラメータは、関数に渡す値です。

※パラメータは、任意の数、任意の型を指定できます。

関数=翻訳機
パラメータ(引数)=りんご
戻り値=apple

みたいなイメージです。

あすか

パラメータを含む関数の構文は以下のとおり。

name(parameter : type) : type =
	codeblock

次の例では、CoinsPerMousetrap が関数 BuyMousetrap() のパラメータになっています。

var Coins : int = 500

BuyMousetrap(CoinsPerMousetrap : int) : void =
    set Coins = Coins - CoinsPerMousetrap
    Print("Mousetrap bought! You have {Coins} coins left.")
  • 最初に、Coins という変数に500という整数値が設定されています(var Coins : int = 500)。
  • 関数 BuyMousetrap() は、CoinsPerMousetrap という整数型のパラメータを受け取ります。
    • このパラメータは、1つのネズミ捕り器の価格を表しています。
    • ただ、この関数が値を返すことは望まないので、型は void とします。
  • 関数の本体では、Coins の値から CoinsPerMousetrap を引き算し、その結果を再び Coins に代入します。
    • これにより、ネズミ捕り器の価格分だけコインが減少します。
  • 最後に、Print() 関数を使ってメッセージを表示します。表示されるメッセージは、残りのコイン数を含んでいます。
    • {Coins} の部分は、変数 Coins の値が埋め込まれます。

引数

UEFN Verse 引数

関数を呼び出す際に、パラメータに値を渡す必要があります。

この渡された値は関数の引数と呼ばれます。

以下の方法を使って関数 BuyMousetrap() を呼び出すことができます。

  1. BuyMousetrap(CoinsPerMousetrap := 10) のように、関数のパラメータを模倣して引数を渡すことができます。
    • ここでの 10 は関数の引数であり、結果の値を変更します。
  2. リテラル値を使用する方法もあります。
    • 例えば、「Verseの基本」「データを格納」で学んだように、パラメータと同じ型のリテラル値を直接使用することができます。
  3. また、事前に宣言した変数や定数を引数として使用することも可能
    • 異なる値を引数として使って関数を呼び出すことで、異なる結果を得ることができます。
var Coins : int = 500
# この呼び出しの後、コインは 490
BuyMousetrap(CoinsPerMousetrap : = 10)

# この呼び出しの後、コインは 485
BuyMousetrap(5)

CoinsPerMouseTrap : int = 20
# この呼び出しの後、コインは 465
BuyMousetrap(CoinsPerMousetrap)

上記のコードは、コインの数量を管理し、ネズミ捕りを購入するための関数を使用する例です。

最初に、変数 Coins が整数値の 500 で初期化されていますよね。

1つ目の呼び出しでは、BuyMousetrap 関数を呼び出しています。

この関数は CoinsPerMousetrap というパラメータを受け取る感じですね。

CoinsPerMousetrap := 10 という引数を指定しているため、ネズミ捕り1つの価格が 10 であるという意味です。

関数内で Coins から CoinsPerMousetrap を引いていますので、呼び出しの後、Coins の値は 490 になります。

あすか

2つ目の呼び出しでは、BuyMousetrap(5) という形式で関数を呼び出しています。

この場合、引数として直接 5 を指定しています。これはネズミ捕り1つの価格が 5 であることを意味します。

同様に、関数内で Coins から CoinsPerMousetrap を引いていますので、呼び出しの後、Coins の値は 485 になります。

3つ目の呼び出しでは、CoinsPerMouseTrap という変数を CoinsPerMousetrap の値として指定しています。

つまり、ネズミ捕り1つの価格は 20 であるということです。

この場合、関数呼び出し時に CoinsPerMousetrap の値が 20 になります。

関数内で Coins から CoinsPerMousetrap を引いていますので、呼び出しの後、Coins の値は 465 になります。

これらの呼び出しを通じて、関数を使用することでコインの数量を更新し、ネズミ捕りを購入することができます。

複数のパラメータ

複数のパラメータ

パラメータをカンマで区切れば、関数にいくつでもパラメータを定義することができます。

2つのパラメータを含む関数の構文は以下のとおり。

name(parameter : type, parameter : type) : type =
    codeblock

関数を呼び出す際にも、引数をカンマで区切る必要があります。これは、関数のパラメータの定義方法を模倣しています。

練習時間

UEFN Verse パラメータを定義 練習問題

前回の練習問題「関数の結果を指定」では、CalculateDamage() 関数を作成しました。

このCalculateDamage() 関数ボディには、パラメータにすればより柔軟に機能する定数と変数が含まれています。

関数は以下のとおりです。

CalculateDamage() : float = 
    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

修正を加える関数では、次の3つのパラメータを使用します。

  • PlayerHealth
    • プレイヤーの現在の体力値
  • DesiredDamageAmount
    • プレイヤーに対して与えられるダメージの最大量
  • MinHealth
    • DesiredDamageAmount によって体力値が 0.0 以下に減少される場合の、プレイヤーの体力値

以下に一致するように関数を更新します。

CalculateDamage(PlayerHealth : float, DesiredDamageAmount : float, MinHealth : float) : float = 
    # ダメージ量によってプレイヤーが倒れない場合は、そのダメージ量を実行します
    if (PlayerHealth > DesiredDamageAmount):
        return DesiredDamageAmount
    else if (PlayerHealth > MinHealth):
        # プレイヤーの体力値が低い場合は、もう一度チャンスを与えます
        return PlayerHealth - MinHealth
    else:
        # プレイヤーを倒します
        return PlayerHealth

この関数は、与えられた体力値やダメージ量を基に、プレイヤーに与えるべきダメージ量を計算します。

まず、プレイヤーの現在の体力値と最大ダメージ量を比較し、プレイヤーが倒れない場合は最大ダメージ量を返します。

次に、プレイヤーの体力値が最低体力値よりも高い場合は、最低体力値を引いた値を返します。

これにより、プレイヤーに対して追加のチャンスを与えることができますね。

最後に、プレイヤーの体力値が最低体力値以下の場合は、プレイヤーを倒したとして現在の体力値を返します。

このように、パラメータを受け取って動作する関数を作成することで、より柔軟に再利用可能なコードを作成することができます。

他の部分でこの関数を呼び出す際には、適切な体力値とダメージ量を指定して関数を実行しましょう。

みなみ

どうして、3つのパラメータを使って関数を定義するのですか?

気になるところですよね。

結論からいうと、コードの効率性と柔軟性が向上するからです。

あすか

関数のパラメータを使用することで外部から値を受け取ることができるため、異なる値や状況にも対応できるようになります。

例えば、先ほどの CalculateDamage() 関数では、プレイヤーの現在の体力値、希望するダメージ量、および最低体力値をパラメータとして受け取ります。

このようにすることで、関数を呼び出す側で異なる値を指定することができます。

関数のパラメータをまとめて使用することで、コードの再利用性も向上します。

同じ処理をするために同じコードを何度も書く必要はありません。

代わりに、関数を呼び出す際に異なるパラメータを指定することで、同じ処理を再利用することができます。

パラメータを使用することで、関数はより柔軟になります。

異なる値や状況に対して同じ処理を行いたい場合でも、パラメータを変更するだけで対応できます。

これにより、コードの保守性も向上します。

そのため、関数のパラメータを効果的に活用することは、効率的で柔軟なコードを作成する上で重要な要素です。

 DesiredDamageAmountの役割

HurtPlayer() 内で CalculateDamage() を呼び出す際に、() 内に赤色の波線が表示されることがあります。

これは、CalculateDamage() の宣言が更新され、3つのパラメータが必須となったにも関わらず、CalculateDamage() の呼び出しで引数を渡していないのが原因です。

以下の手順でこれらを修正します。

PlayerHealth の引数を CalculateDamage() に渡す前に、キャラクターの現在の体力値を知る必要があります。

このためには、GetHealth() メソッドを使用します。

GetHealth() メソッドは、Damage()Heal() と同様に呼び出しますが、その結果は HurtPlayer() 関数内で保存する必要がある値が返されます。

 HurtPlayer() : void =
     Playspace : fort_playspace = GetPlayspace()
     AllPlayers : []player = Playspace.GetPlayers()
     if (FirstPlayer : player = AllPlayers[0]):
         if (FortniteCharacter : fort_character = FirstPlayer.GetFortCharacter[]):
             MyCharacterHealth : float = FortniteCharacter.GetHealth()
             DamageToDo: float = CalculateDamage()
             Print("DamageToDo: {DamageToDo}")
             FortniteCharacter.Damage(DamageToDo)

CalculateDamage() の2番目のパラメータについては、HurtPlayer() からのパラメータが必要になります。

そのパラメータを今から作成します。

DamageAmount という float パラメータを追加します。HurtPlayer() は次のようになるはずです。

 HurtPlayer(DamageAmount : float) : void =
     Playspace: fort_playspace = GetPlayspace()
     AllPlayers: []player = Playspace.GetPlayers()
     if (FirstPlayer : player = AllPlayers[0]):
         if (FortniteCharacter : fort_character = FirstPlayer.GetFortCharacter[]):
             MyCharacterHealth : float = FortniteCharacter.GetHealth()
             DamageToDo : float = CalculateDamage()
             Print("DamageToDo: {DamageToDo}")
             FortniteCharacter.Damage(DamageToDo)

CalculateDamage() に追加する3つの引数がすべて準備できました。

  • PlayerHealth パラメータ のための MyCharacterHealth
  • DesiredDamageAmount パラメータ のための DamageAmount
  • MinHealth パラメータ のための 1.0

HurtPlayer() は次のようになり、エラーは生じなくなるはずです。

HurtPlayer(DamageAmount : float) : void =
    Playspace: fort_playspace = GetPlayspace()
    AllPlayers: []player = Playspace.GetPlayers()
    if (FirstPlayer : player = AllPlayers[0]):
        if (FortniteCharacter : fort_character = FirstPlayer.GetFortCharacter[]):
            MyCharacterHealth : float = FortniteCharacter.GetHealth()
            DamageToDo : float = CalculateDamage(MyCharacterHealth, DamageAmount, 1.0)
            Print("Damage To Do: {DamageToDo}")
            FortniteCharacter.Damage(DamageToDo)

HurtPlayer()関数を数回呼び出し、プレイヤーの体力値に応じた異なるエフェクトを確認します。

次に、HealPlayer()関数の更新方法について考えてみましょう。

HealPlayer()関数は、与えられた回復量に基づいてプレイヤーの体力値を増やす役割を果たします。

さらに、便利なメソッドであるSetMaxHealth()があります。

このメソッドは、Damage()Heal()GetHealth()と同様に呼び出すことができます。

SetMaxHealth()メソッドと、あなたが知っている関数とパラメータに関する知識を活用して、HealPlayer()関数を更新することができます。

プレイヤーが楽しむことや興味を持つことを考慮して、どのような更新を行うか検討してみましょう。

まとめ

UEFN Verse パラメータを定義 まとめ

今回は、関数でパラメータを定義して必要な結果を得る方法について解説しました。

 今回のまとめ
  • **パラメータは、関数シグネチャの括弧の中で宣言されている定数です。
  • 引数 はその関数のパラメータで使用する定数に代入された値です。
  • 1 つの関数の中でカンマを使って 複数のパラメータを区切る 必要があります。

また、今回の演習で扱ったコードは以下のとおりです。

 完全なスクリプト
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(80.0)
        Print("Player Hurt")

    CalculateDamage(PlayerHealth : float, DesiredDamageAmount : float, MinHealth : float) : float = 
        # ダメージ量によってプレイヤーが倒れない場合は、そのダメージ量を実行します
        if (PlayerHealth > DesiredDamageAmount):
            return DesiredDamageAmount
        else if (PlayerHealth > MinHealth):
            # プレイヤーのヘルス値が低い場合は、もう一度チャンスを与えます
            return PlayerHealth - MinHealth
        else:
            # プレイヤーを倒します
            return PlayerHealth

    HurtPlayer(DamageAmount : float) : void =
        Playspace: fort_playspace = GetPlayspace()
        AllPlayers: []player = Playspace.GetPlayers()
        if (FirstPlayer : player = AllPlayers[0]):
            if (FortniteCharacter : fort_character = FirstPlayer.GetFortCharacter[]):
                MyCharacterHealth : float = FortniteCharacter.GetHealth()
                DamageToDo : float = CalculateDamage(MyCharacterHealth, DamageAmount, 1.0)
                FortniteCharacter.Damage(DamageToDo)
                Print("{DamageToDo} damage dealt to player")

    HealPlayer(HealAmount : float) : void =
        Playspace: fort_playspace = GetPlayspace()
        AllPlayers: []player = Playspace.GetPlayers()
        if (FirstPlayer : player = AllPlayers[0]):
            if (FortniteCharacter : fort_character = FirstPlayer.GetFortCharacter[]):
                FortniteCharacter.Heal(HealAmount)

次回は、Verse 言語のクイック リファレンスについてやっていきます。

ひとまず、お疲れさまでした🍵

※参考文献:Epic Games

  • この記事を書いた人
  • 最新記事

あすか(Asuka)

自己紹介:UEFNクリエイター兼ブロガー
Verse言語独学中 | UE・プログラミング・3Dモデリング完全初心者 | 備忘録として学習記録をブログに残しています。
■好きな言葉
徳は弧ならず必ず隣あり.
■ひとこと
まだまだ未熟者ですが、
よろしくお願いします。

-UEFN, Verse言語, メタバース
-, ,