| Home Page | Recent Changes | Preferences

Static Function

Syntax

static <other function modifiers> function/operator <type> <function name> ( <parameters> )
{
  ...
}

Static functions which are declared as final are automatically simulated as well.

See also Function syntax.

Calling A Static Function

Static functions can be called like any other function or using this special syntax:

class'ClassName'.static.FunctionName(...);

In other words, they can be called without an object of that class available. You can also substitute a class variable, like so:

RunTimeClass.static.FunctionName(...);

Restrictions Of Static Functions

Static functions can only access variables passed to them as parameters or the default values of variables. They can only call other static functions.

Uses and Implentation

Static functions have few uses, but they do exist - they can be used for a couple of things in my experience:

  1. A class that contains "global" functions - for instance math functions that you may want to be used by various classes that are not derived from a single parent class that can be readily modified. By that I mean something like a pawn and a projectile that both require the same function - although you can subclass actor and put the functions there, pawn and projectile both provide native code that would be lost if you subclassed actor then made your own pawn/projectile class. So this can be used to access those functions.
  2. A highly flexible predefined variable. This is how I use static functions - meshes are bundled with their animations so that the actual animation name is not used. A "meshcontroller" static object has static functions which return the appropriate animation and mesh for that meshcontroller. Then, instead of setting a mesh for an actor, you give your classes a class<meshcontroller> and then use the static function to return animation names within the PlayAnim call and the mesh can be returned and set in postbeginplay. You can even use this to have random animations on meshes that have multiple animations and not on others that have only one - it's all modular and transparent to the class that's actually calling the playanim.

Here is an example of the above:

  LoopAnim( MyMesh.static.GetAttackAnim(), MyMesh.static.GetAttackAnimRate() );

And in the meshcontroller class:

  const numAttackAnims=3;

  // Didn't use an array to make this easier to expand by subclasses.
  var name AttackAnim1, AttackAnim2, AttackAnim3;
  var float AttackAnimRate1, AttackAnimRate2, AttackAnimRate3;

  static function name  GetAttackAnim()
  {
    local int Temp;

    Temp = INT( FRand() * numAttackAnims );
    switch( Temp )
    {
      case 0: return  Default.AttackAnim1; break;
      case 1: return  Default.AttackAnim2; break;
      case 2: return  Default.AttackAnim3; break;
      default: return Default.AttackAnim1; break;
    }
  }

  etc...

The problem with that is that if you have multiple attack animations that are random you might not get the matching animrate and attackanim, so you could remedy that as follows:

  Temp = MyMesh.static.RandomizeAttack();
  LoopAnim( MyMesh.static.GetAttackAnim( Temp ), MyMesh.static.GetAttackAnimRate( Temp ) );

And in the meshcontroller class:

  const numAttackAnims=3;

  // Didn't use an array to make this easier to expand by subclasses.
  var name AttackAnim1, AttackAnim2, AttackAnim3;
  var float AttackAnimRate1, AttackAnimRate2, AttackAnimRate3;

  static function int   RandomizeAttack()  { return INT( FRand() * numAttackAnims; }
  static function name  GetAttackAnim( int AnimNum )
  {
    switch( AnimNum )
    {
      case 0: return  Default.AttackAnim1; break;
      case 1: return  Default.AttackAnim2; break;
      case 2: return  Default.AttackAnim3; break;
      default: return Default.AttackAnim1; break;
    }
  }

  etc...

That, however would be slightly hack-ish. Here's an even better way.

  MyMesh.static.PlayAttackAnim( self );

And in the meshcontroller class:

  const numAttackAnims=3;

  // Didn't use an array to make this easier to expand by subclasses.
  var name AttackAnim1, AttackAnim2, AttackAnim3;
  var float AttackAnimRate1, AttackAnimRate2, AttackAnimRate3;

  static function PlayAttackAnim( actor HaplessVictim )
  {
    local int Temp;

    Temp = INT( FRand() * numAttackAnims );
    switch( Temp )
    {
      case 0:  HaplessVictim.PlayAnim( Default.AttackAnim1, Default.AttackAnimRate1 ); break;
      case 1:  HaplessVictim.PlayAnim( Default.AttackAnim2, Default.AttackAnimRate2 ); break;
      case 2:  HaplessVictim.PlayAnim( Default.AttackAnim3, Default.AttackAnimRate3 ); break;
      default: HaplessVictim.PlayAnim( Default.AttackAnim1, Default.AttackAnimRate1 ); break;
    }
  }

Problems Using Enumerated Variables in Static Functions

  • DJPaul: I couldn't get enums to work with these.
  • Foxpaw: I believe the problem that you are having with enums is (though I haven't tested it) that you can only pass an enum as an argument in a function if it is the same enum declared in both the sending and recieving classes. This means that it actually has to be the same enum, declared in a superclass of both of the classes in question. The fact that it may be an identical enum is not sufficient unless you want to get into funky casting. I intend to test this soon to find out if that is indeed the case and will update this page with the results. I had a problem similar to this, though with a non-static function, and that seems to be the logical cause, but I will test it to find out. If that is not the case you can use an int or a byte (I think you can use a byte) as the actual function argument and then use constants within the static function. Other than that the rest of your code can remain intact because the enum should be converted to a standard byte/int when it is sent to the function and the constants will be replaced by their numerical equivalent at runtime. This is what I did until I realized that the system I was using would run very slow over network due to the way that replication works.

Foxpaw: I removed some of the redundant stuff.. I left that stuff in when I refactored this page ages ago because I don't really like removing other people's contributions, even if they do seem redundant.. but since the call came to refactor this page I went ahead and removed the conversaition at the end. Mmm, my writing style has changed so much... this looks nothing like the Karma page. It does look a bit like a tutorial, I wanted to be as clear as possible because there seems to be some confusion on why a person would use a static function.

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Image Uploads

Random Page

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

Mapping Topics

Mapping Lessons

UnrealEd Interface

Questions&Answers

Scripting Topics

Scripting Lessons

Making Mods

Class Tree

Questions&Answers

Modeling Topics

Questions&Answers

Log In