UDN
Search public documentation:

GFxVolumeStatusBarJP
English Translation
中国翻译
한국어

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 ホーム > ユーザーインターフェイスと HUD > 「Scaleform GFx」 > ステータスバーをともなったコントロールボリュームの追加方法

ステータスバーをともなったコントロールボリュームの追加方法


概要


このチュートリアルでは、動作しているステータスバーをともなった、非常に基本的なコントロールボリュームを追加する方法について解説します。このチュートリアルには 3 つのバージョンがあります。バージョン 1 は、バージョン 2 またはバージョン 3 のオプションのコードを追加する前に、完了しておく必要があります。

  • ステータスバーは、HUD 上の中心に、スクリーンに描画されます。
  • ステータスバーは、ホバリングバーとしてコントロールボリュームの中央に表示されます。物理的にはゲームワールドに存在しますが、常にプレイヤーと向き合います。
  • このステータスバーは、再度 HUD 上に描画されます。今回は、Canvas.Project によって、コントロールボリュームの相対位置に描画されます。ステータスバーは、常にコントロールボリュームに関連づけられて配置されるため、プレイヤーが動くにともなって HUD 上を動き回ります。

このチュートリアルでは、すでにキャプチャされているボリュームを別のプレイヤーやチームがキャプチャするためのコードを提供していません。また、2 人以上のプレイヤーのキャプチャの試みを統合するためのコードも提供していません。これらについては、ご自分で開発する必要があります。

完了すると、Brush->Add Volume->SFControlVolume により、エディタで、ボリュームをレベルに追加することができるようになります。

「Flash」のセットアップ


  • 新たな AS 2 ドキュメントを作成します。
  • ドキュメントのサイズを 512×256 にセットします。
  • ALERT! 重要 : ドキュメントの背景 (background) を black にセットします。
  • ドキュメントの中央に青い長方形を作成します。
  • これをムービークリップに変換します。
  • これに BlueStatusBar というインスタンス名を付けます。
  • この SWF ファイルを UDK インストールに保存、パブリッシュします。場所は、/UDKGame/Flash/UDKSFTutorial/CVStatusBar.SWF の下です。
  • SWF ファイルを UDK にインポートします。

Scaleform_Tutorial_01.jpg

HUD 中央のステータスバー


マップ内の任意の場所に配置可能な実際のコントロールボリュームを作成します。

SFControlVolume.uc
class SFControlVolume extends Volume
  placeable;

var bool bControlled;
var int ElapsedTime;
var int PercentCaptured;

// Editable Properties
var(TimeToControl) int TimeToControl;
var(TimeToControl) float UpdateRate;
var() SwfMovie Movie;

var Info ControlTimer;
var SFControlVolumeMovie CVMovie;

event PostBeginPlay()
{
  Super.PostBeginPlay();
  ControlTimer = Spawn(class'SFVolumeControlTimer', self);
}

event Touch(Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal)
{
  Super.Touch(Other,OtherComp,HitLocation,HitNormal);

  if(!bControlled)
  {
    // Turn on the timer, and have it tick every X seconds, where X = UpdateRate.
    ControlTimer.SetTimer(UpdateRate,true);
  }

  // Only display the status bar when the player has touched/is in the volume.
  CreateControlVolumeMovie();
  UpdateStatusBar();
}

event UnTouch(Actor Other)
{
  Super.UnTouch(Other);

  // Reset capture timer.
  ControlTimer.ClearTimer();

  // Close the status bar when the player leaves the volume.
  CVMovie.Close(true);
  CVMovie = none;

  if(!bControlled)
  {
    ElapsedTime = 0;
  }
}

function StartControlling(SFVolumeControlTimer VC)
{
  local int PercentCaptured;

  if (VC == ControlTimer)
  {
    ElapsedTime++;
    `log("Time to capture: " @ TimeToControl - ElapsedTime);

    UpdateStatusBar();

    // Once we reach the total time to control, capture the volume and clear the timer.
    if(ElapsedTime >= TimeToControl)
    {
      `log("Captured!");
      bControlled = true;
      ControlTimer.ClearTimer();
    }
  }
}

function UpdateStatusBar()
{
  PercentCaptured = (100 * float(ElapsedTime)) / float(TimeToControl);
  CVMovie.UpdateStatusBar(self, PercentCaptured);
}

function CreateControlVolumeMovie()
{
  CVMovie = new class'SFControlVolumeMovie';
  CVMovie.MovieInfo = Movie;
  CVMovie.SetTimingMode(TM_Real);
  CVMovie.Start();
}

defaultproperties
{
  TimeToControl=100
  UpdateRate=0.1
}

次に、timer クラスを作成します。このクラスは、ティックするたびに、SFControlVolume::StartControlling() 関数を実行するにすぎません。

SFVolumeControlTimer.uc
class SFVolumeControlTimer extends Info;

var SFControlVolume CV;

event PostBeginPlay()
{
  Super.PostBeginPlay();
  CV = SFControlVolume(Owner);
}

event Timer()
{
  CV.StartControlling(self);
}

defaultproperties
{
  TickGroup=TG_PreAsyncWork
  bStatic=false
  RemoteRole=ROLE_None
}

最後に、ステータスバーのための Movie Player クラスを作成します。

SFControlVolumeMovie.uc
class SFControlVolumeMovie extends GFxMoviePlayer;

var GFxObject StatusBarMC;

function bool Start(optional bool StartPaused = false)
{
  Super.Start();
  Advance(0);

  StatusBarMC = GetVariableObject("_root.BlueStatusBar");

  return true;
}

function UpdateStatusBar(SFControlVolume CV, int PercentCaptured)
{
  local GFxObject.ASDisplayInfo DI;

  DI.hasXScale = true;
  DI.hasAlpha = true;

  DI.XScale = PercentCaptured;
  DI.Alpha = 100;

  if (DI.XScale >= 100)
  {
    DI.XScale = 101;
  }
  else if (DI.XScale == 0)
  {
    DI.XScale = 1;
    DI.Alpha = 0;
  }

  StatusBarMC.SetDisplayInfo(DI);
}

defaultproperties
{
    bDisplayWithHudOff = false
}

  • 次に、BSP ビルダーブラシを使用して、コントロールボリュームをレベルに追加します。
  • ボリュームのプロパティに進みます。(F4)。
  • Time を Control にセットします。(キャプチャするティックの最大数)。
  • Update Rate (更新率) をセットします。(ステータスバーをどのくらいの頻度で「ティック」するかを秒単位でセットします。この値が小さくなるほど、ティック時間が速くなります)。
  • Movie フィールドを、すでにインポートしている SWF にセットします。
  • レベルを保存して、テストします!

ゲームワールドに浮遊するステータスバー


ステータスバーを物理的にゲームワールドに配置する (ボリュームの中心に) のであれば、まず、SFControlVolume クラスを変更する必要があります。

ALERT! 注意 : 複数のコントロールボリュームをレベルに追加することができるようになりますが、各ボリュームのために、ユニークな Material と TextureRenderTarget2D を作成する必要があります。

SFControlVolume の変更 :

SFControlVolume.uc
// Add these global vars to the top of the class
var() StaticMesh Mesh;
var() vector TranslationOffset;
var() array<MaterialInterface> Materials;
var() TextureRenderTarget2D RenderTexture;
var SFControlVolumeMesh CVMesh;

// Add this code to the event Touch() function, just after Super.Touch();
CVMesh = Spawn(class'SFControlVolumeMesh');
CVMesh.Mesh.SetStaticMesh(Mesh);
CVMesh.Mesh.SetMaterial(0,Materials[0]);
CVMesh.SetLocation(self.Location + TranslationOffset);
CVMesh.PC = Other;

// Add this line of code to the event UnTouch() function
CVMesh.Destroy();

// Add this line of code to the CreateControlVolumeMovie() function, after CVMovie.MovieInfo = Movie;
CVMovie.RenderTexture = RenderTexture;

次に、新たなクラスを作成します。このクラスは、ゲームワールドにステータスバーを表示するために使用されます。

SFControlVolumeMesh.uc
class SFControlVolumeMesh extends StaticMeshActor
  placeable;

var vector PlayerLoc;
var actor PC;

var() editinline const StaticMeshComponent Mesh;

function Tick(float fDeltaTime)
{
  Super.Tick(fDeltaTime);

  // Always face the player
  PlayerLoc = PC.Location;
  SetRotation(Rotator(PlayerLoc - self.Location));
}

defaultproperties
{
  bStatic = false
  bMovable = true

  Begin Object class=StaticMeshComponent Name=StaticMeshComp1
    CollideActors = False
    BlockActors = false
    BlockRigidBody = False
  End Object
  Mesh = StaticMeshComp1
  Components.Add(StaticMeshComp1)
}

  • 次に、BSP ビルダーブラシを使用して、コントロールボリュームをレベルに追加します。
  • ボリュームのプロパティに進みます。(F4)。
  • Time を Control にセットします。(キャプチャするティックの最大数)。
  • Update Rate (更新率) をセットします。(ステータスバーをどのくらいの頻度で「ティック」するかを秒単位でセットします。この値が小さくなるほど、ティック時間が速くなります)。
  • Movie フィールドを、すでにインポートしている SWF にセットします。
  • コンテンツブラウザを開きます。
  • 新たな TextureRenderTarget2D に好きな名前を付け、さらに、解像度を 512×256 にセットすることによって、SWF に合わせます。
  • 新たな Material (マテリアル) を作成し、好きな名前を付けます。
  • Material 内で、新たな TextureSample を追加します。
  • 新たな TextureSample の Texture フィールドに、TextureRenderTarget2D を挿入します。
  • TextureSample の Diffuse (ディフューズ) の出力 (黒い四角) を、Material の Diffuse の入力に接続します。
  • Material の Blend Mode (ブレンドモード) を BLEND_AlphaComposite (アルファ合成) にセットします。
  • Color->New Desaturation (新たなデサチュレーション) を追加します。
  • Parameters->New ScalarParameter (新たなスカラーパラメータ) を追加します。
  • Parameter (パラメータ) の Default Value (デフォルト値) を -20 にセットします。
  • TextureSample の Diffuse の出力 (黒い四角) を、Desaturation (デサチュレーション) の A に接続します。
  • Param 'None' (なし) を Desaturation の B に接続します。
  • Desaturation の出力を、Material の Opacity (オパシティ) と Emissive (エミッシブ) に接続します。
  • Material ウィンドウを閉じて、保存します。
  • 新たなマテリアルとレンダリング テクスチャを有するパッケージを保存します。
    Scaleform_Tutorial_02.jpg
  • ボリュームのプロパティに進みます。(F4)。
  • Mesh (メッシュ) フィールドを、平面型のメッシュ (例 : dwStaticMeshes.Plane にあるような) にセットします。
  • Translation Offset (平行移動オフセット) をセットします。(これによって、ステータスバーが、コントロールボリュームの中心に相対化されて (関連付けられて) 移動します)。
  • 新たな Material スロットを追加します。
  • 作成した新たなマテリアルを、Material スロット 0 にアサインします。
  • 作成した TextureRenderTarget2D を、RenderTexture フィールドにアサインします。
  • レベルを保存して、テストします!

相対位置にある HUD 上のステータスバー


このバージョンは、Canvas Project (キャンバス プロジェクト) を使用して、ボリュームの相対位置にステータスバーを HUD 上で描画します。見回すと、ステータスバーが HUD 上で動くため、相対位置が変わりません。

ALERT! 注意 : 上記の改変をコードに加えている場合は、それを元に戻してください。

HUD ラッパーの PostRender() 関数を改変する必要があります。

YourHUD.uc
event PostRender()
{
  local SFControlVolume SFCV;

  super.PostRender();

  // Find all control volumes in the level
  foreach WorldInfo.AllActors(class'SFControlVolume',SFCV)
  {
    //Project 3D world position of control volume to 2D screen position
    if (SFCV.CVMovie != none)
    {
      SFCV.CVMovie.UpdatePosition(Canvas.Project(SFCV.Location));
    }
  }

  // Tick HUD
  if (HudMovie != none)
  {
    HudMovie.TickHud(0);
  }
}

SFControlVolumeMovie.uc の改変 : まず、新たなグローバル変数を 2 個追加します。

SFControlVolumeMovie.uc
var int Width, Height;

次に、以下の 3 行のコードを Start() 関数に追加します。

SFControlVolumeMovie.uc
function bool Start(optional bool StartPaused = false)
{
    local float x0, y0, x1, y1;

    super.Start();
    Advance(0.0);

    StatusBarMC = GetVariableObject("_root.BlueStatusBar");

    GetVisibleFrameRect(x0, y0, x1, y1);
    Width = x1-x0;
    Height = y1-y0;

    return true;
}

さらに、以下の関数を、UpdateStatusBar() 関数の直後に追加します。

SFControlVolumeMovie.uc
function UpdatePosition(Vector ScreenPos)
{
    self.SetViewPort(ScreenPos.X,ScreenPos.Y,Width,Height);
}

Scaleform_Tutorial_03.jpg