【UEFN】Verse言語で「均等にチーム分けをする仕組み」を実装する

目次

コードの全体

using { /UnrealEngine.com/Temporary/Diagnostics } 
using { /Fortnite.com/Devices } 
using { /Verse.org/Simulation } 
using { /Fortnite.com/FortPlayerUtilities } 



Team_Setter_Device := class(creative_device): 
    @editable var PregameTimer : timer_device = timer_device{} 
    @editable var PregameCounter : player_counter_device = player_counter_device{} 
    @editable var HudPregame : hud_controller_device = hud_controller_device{} 
    @editable var HudGameStart : hud_controller_device = hud_controller_device{} 
    @editable var Teleporters : [] teleporter_device = array{} 
    var Teams : []team = array{} 

  

    OnBegin<override>()<suspends> : void = 
        PregameCounter.CompareToTarget() 
        PregameCounter.CountSucceedsEvent.Subscribe(StartPregameTimer) 



    StartPregameTimer() : void= 
        PregameTimer.Start() 
        PregameTimer.SuccessEvent.Subscribe(SplitTeams) 

  
  
    SplitTeams(Agent : ?agent) : void= 
            set Teams = GetPlayspace().GetTeamCollection().GetTeams() 
            AllPlayers := GetPlayspace().GetPlayers() 
            GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded) 
            BalanceTeams() 
            TeleportPlayersToStartLocations() 
            PregameCounter.Disable() 
            
            
            
    OnPlayerAdded(InPlayer : player) : void = 
        BalanceTeams() 
        TeleportPlayersToStartLocations()             

  
  
    BalanceTeams() : void = 
        AllPlayers := GetPlayspace().GetPlayers() 
        for(TeamPlayer:AllPlayers,CurrentTeam:= GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): 
            var TeamSize:int = 0 
            if(setTeamSize= GetPlayspace().GetTeamCollection().GetAgents[CurrentTeam].Length): 
            SmallestTeam : ?team = FindSmallestTeam(TeamSize) 
            if(TeamToAssign:=SmallestTeam?, GetPlayspace().GetTeamCollection().AddToTeam[TeamPlayer, TeamToAssign]): 
            
            
            
    FindSmallestTeam(CurrentTeamSize : int) : ?team = 
        var SmallestTeam : ?team = false 
        var TeamSize : int = CurrentTeamSize 

        for(Team:Teams,CandidateTeamSize:= GetPlayspace().GetTeamCollection().GetAgents[Team].Length, TeamSize > CandidateTeamSize): 
            set SmallestTeam = option{Team} 
            set TeamSize = CandidateTeamSize 
        return SmallestTeam  

  

    TeleportPlayersToStartLocations():void= 
        for: 
            TeamIndex -> PlayerTeam:Teams  
            TeamPlayers:= GetPlayspace().GetTeamCollection().GetAgents[PlayerTeam] 
            TeamTeleporter := Teleporters[TeamIndex] 
            Transform := TeamTeleporter.GetTransform() 

        do: 
            for(TeamPlayer:TeamPlayers): 
                TeamPlayer.Respawn(Transform.Translation, Transform.Rotation) 

コードの解説

冒頭

この仕組みでは タイマーの仕掛け、プレイヤーカウンター、HUDメッセージの仕掛け、テレポーターを使うため、9~13行目でそれぞれ定義します。 

14行目で後にゲーム内のteam情報が配列として入るTeams変数を定義します。 

関数宣言

24行目からStartPregameTimer関数を定義しています。 
コードブロックの意味は以下の通りです。 

1.タイマーを開始 
2.タイマーの設定時間が過ぎたらSplitTeams関数を呼び出す(チーム分け実施) 



30行目からSplitTeams関数を定義しています。 
コードブロックの意味は以下のようになります。 

1.ゲーム内の全てのチームのteam情報を取得 
2.ゲーム内の全てのプレイヤーのplayer情報を取得 
3.ゲームに新たなプレイヤーが参加したらOnPlayerAdded関数を呼び出す(チーム分けのメンバーに入れる) 
4.BalanceTeams関数を呼び出す(チーム分けを実施する) 
5.TeleportPlayersToStartLocations()関数を呼び出す(プレイヤーをスタート地点にテレポートする) 
6.プレイヤーカウンターを無効にする 

31行目でTeams変数にゲームに存在するチームのteam情報を配列としてセットします。 
よく出てくる式なのでこのまま覚えておくと便利です。 

32行目でAllPlayersにゲーム内の全てのプレイヤーのplayer情報を配列として入れています。 これもよく出てくる式です。 

33行目はゲームに新たなプレイヤーが参加したらそのプレイヤーをチーム分けのメンバーに入れるための式です。 このSubscribeを使った式の形もよく出てきます。 


46行目でBalanceTeams関数を宣言しています 
コードブロックの意味は以下のようになります。 

1.ゲーム内の全てのプレイヤーのplayer情報を取得 
2.全てのプレイヤーに以下を実施 
プレイヤーが今所属しているチームのteam情報を取得 
そのチームの所属人数を取得 
最も人数が少ないチームを取得 
そのチームにプレイヤーを入れる 


48行目はforを使って各プレイヤーにコードブロックないの式を実行しています。 
GetTeam[TeamPlayer]でプレイヤーのteam情報を取得しCurrentTeamに入れます。 


50行目でGetAgents[CurrentTeam]により、チーム内の全てのプレイヤーのagent情報を配列として取得し、その後ろにLengthを書いています。 
これにより、配列の要素の数、つまりチーム内のプレイヤーの数を取得できます。 

51行目では、後ほど出てくるFindSmallestTeam関数により最も人数が少ないチームのteam情報を取得し、SmallestTeam定数に入れています。 

52行目で、オプション型であるSmallestTeamにアクセスし、AddToTeam[TeamPlayer, TeamToAssignによりそのチームにプレイヤーを加えます。 



56行目からFindSmallestTeam関数を宣言しています。 
コードブロックの意味は以下のようになります。 

各チームに以下を実行 
チームの人数がプレイヤー(BalanceTeamsのforの対象のプレイヤー)の属しているチームより少ない場合、このチームをSmallestTeamとして値を返す

58行目のTeamSizeはFindSmallestTeam関数呼び出し時の引数が入るため、BalanceTeamsのforの対象のプレイヤーの属しているチームの人数が入ることになります。 

60行目のforでゲームに存在する各チームの人数であるCandidateTeamSizeとTeamSizeを比べ、CandidateTeamSize方が小さい場合、そのチームがSmallestTeamとなります。 
TeamSizeの方が小さい場合、式が失敗しコードブロックの式は実行されずロールバックされます。 
これにより、人数の多いチームにいるプレイヤーを人数が少ないチームに移動させることができます。 

62行目のset TeamSize = CandidateTeamSizeは、SmallestTeamが1度決まったらfor(48行目)のそのプレイヤーの回はSmallestTeamを変更させないためです。 


67行目からTeleportPlayersToStartLocations関数を宣言しています。 
コードブロックの意味は以下のようになります。 

各チームに対応するテレポーターの位置情報を取得 
その位置に各プレイヤーをチームに応じてテレポート 

TeamIndex -> PlayerTeam:Teamsはforの繰り返しの回数を指定する部分です。 

PlayerTeam:Teamsだけの方がよく見る形ですが、TeamIndex ->が付くことで、配列のインデックスも取得できます。
今回は、71行目でテレポーターの配列にアクセスする際に使うため、付けています。 

75行目のfor~は各プレイヤーを取得した位置にリスポーンします。 

OnBegin~

18行目からゲーム開始時に実行されるコードです。
コードブロックの意味は以下の通りです。

1.設定した人数にプレイヤーが到達したかチェック
2.到達したらStartPregameTimer

よかったらシェアしてね!

この記事を書いた人

メタバースに興味を持ち、UEFN、Verseを学びながらFortniteでゲーム制作しています。
初心者でも理解できるような記事を書くことを心がけております。
間違いがありましたら指摘よろしくお願いいたします。

コメント

コメントする

目次