A List of functions to call - is there a better solution?

Hi to all!

In my game, I need the consequences of player actions (i.e. which functions are triggered) to be highly customizable. I had started out like this (abstract example, ResponseModes is an enum):

function PlayerTappedTarget()
{
    if(responseMode == ResponseModes.Nice)
    {
        TellPlayerSomethingNice();
        score++;
    }
    else if(responseMode == ResponseModes.Antagonist)
    {
        TellPlayerSomethingNasty();
        BlockControls();
        score = -1000000;
    }
    else if(responseMode == ResponseModes.None//and so on
    {}
} 

The problem with this approach is that I need lots of ResponseModes, and it seemed a bit clumsy. So I’m trying another approach:

enum Responses
{
   TellPlayerSomethingNice,
   IncreasePlayerScore,
   TellPlayerSomethingNasty,
   DecreasePlayerScore,
   etc...
}



public var tapResponses : List.<Responses>; //defined in the inspector, may be modified at runtime

function PlayerTappedTarget()
{
    DoResponsesList(tapResponses);
}

 function DoResponsesList(responseList : List.<Responses>)
{
    for(response in responseList)
    {
         switch(response)
         {
             case Responses.TellPlayerSomethingNice:
             TellPlayerSomethingNice();
             break;

             case Responses.IncreasePlayerScore:
             score++;
             break;
                          //and so on
         }   
    }
}

Is there a more elegant way to do this? I have about 25 different Responses, in case…

Thanks in advance for your insights!

Yeah i would consider making a design where you don’t have the logic in the loop.
Have the logic predefined and just call it in the loop.

Rough idea.

enum ResponseEnum:
     responeNice
     responseNasty

public CurrentResponse as ResponseEnum = ResponseEnum.responseNice

struct ResponseStruct:
       response as ResponseEnum
       codeBlock as callable 
       OR      // the OR is not code it is psedo programming
                // for showing an alternative
       functionList as List

code1 as List = [TellPlayerSomethingNice, { return { changeScore(1) } } ]
OR
code1 as callable =
{ TellPlayerSomethingNice();
    changeScore(1);
}
responseStruct1 as Response = Response(response: ResponseEnum.responseNice,
                                codeBlock: code1 OR functionList: code1) 
_responseHash = { responseStruct.response: responseStruct1}

def PlayerTappedTarget():
    ExecuteResponse(CurrentResponse)

def ExecuteResponse(responseStruct as ResponseStruct):
    correctResponse = _responseHash[responseStruct.response]
    for functionCall as callable in correctResponse.functionList:
        functionCall()
    OR
    correctResponse.codeBlock()

Hope yon understand a little of what i am trying to say :p.

why not use classes and virtual functions?

You could make a base class called response and make each child a different response.

here’s and example I’ve done (virtual and override are implicit in unityscript):

Declaration (you could even define these in a separate script file):

public class UpgradeBase
{
    protected int curSelection = 0, prevSelection = 0;
    protected string description, title;
    public List<GameObject> mesh;
    protected Selection type = Selection.None;

    public virtual void UpdateSelection(int _var) { }
    public virtual void SelectionLoop() { }
    public virtual void RenderUpdate() { }
    public virtual void Reset() { }
    public virtual int GetSelection() { return curSelection; }
    public virtual void SetSelection(int _selection) { curSelection = prevSelection = _selection; }
}
public class TurretUpgrade : UpgradeBase { protected Selection type = Selection.Turret;}
public class MachineGunUpgrade : UpgradeBase { protected Selection type = Selection.MG;}
public class PaintUpgrade : UpgradeBase
{
    protected Selection type = Selection.Paint;
    public override void Reset() { }
    public override void RenderUpdate() { }
    public override void SelectionLoop() { }
}
public class OptionalUpgrade : UpgradeBase{
    public override void SelectionLoop(){}
    public override void RenderUpdate(){}
}
public class ArmorUpgrade : OptionalUpgrade { protected Selection type = Selection.Armor;}
public class WeaponUpgrade : OptionalUpgrade { protected Selection type = Selection.Weapon;}
public class ExhaustUpgrade : OptionalUpgrade { protected Selection type = Selection.Exhaust;}

basically, you define you base attributes. Then you change them to be overridden for you case. Create a list of your base class:

public List<UpgradeBase> upgrades = new List<UpgradeBase>();

Here’s instantiation of the elements into your list:

upgrades.Add(weapon);
upgrades.Add(armor);
upgrades.Add(skin);
upgrades.Add(turret);
upgrades.Add(mg);
upgrades.Add(exhaust);

then you can call one function like this:

public void UpdateSelection(Selection _selected, int _var){
    upgrades[(int)selected].UpdateSelection(_var);
    }

Just make sure the order you add them to the list matches your enum:

public enum Selection { Weapon, Armor, Paint, Turret, MG, Exhaust, None }

(please excuse a few inconsistencies in the naming)

Might be a bit overkill, but it makes adding new elements and sub elements a lot easier.

It sounds kinda like you’d want to use delegates? Specifically, in this case, an array of functions that matches the enum:

enum Responses
{
	TellPlayerSomethingNice,
	IncreasePlayerScore,
	TellPlayerSomethingNasty,
	DecreasePlayerScore
}

public var tapResponses : List.<Responses>;
private var functions = [
	TellPlayerSomethingNice,
	IncreasePlayerScore,
	TellPlayerSomethingNasty,
	DecreasePlayerScore
];

function DoResponsesList (responseList : List.<Responses>)
{
	for (response in responseList)
	{
		functions[response]();		
	}
}

function TellPlayerSomethingNice () {
	Debug.Log ("You're nice!");
}

function IncreasePlayerScore () {
	score++;
}

function TellPlayerSomethingNasty () {
	Debug.Log ("You stink!");
}

function DecreasePlayerScore () {
	score--;
}

The important thing is that the list of functions matches the order of the enum, not that the names are the same. Doing “functions[0]()” will run the first function in the functions array, for example.

Instead of calling a method like “IncreaseScore()” you can send your game object the message “IncreaseScore”. The receiving game object handles the message by having an actual method of that name.

Have a look at the docs for SendMessage to see what I mean.

This eliminates the need for your switch statement. You can even include one parameter with the message, though none of the example responses you posted have any arguments so maybe you don’t need that.

(Edit: For this scenario I would recommend using the RequireReciever option, to avoid messages failing silently due to typos.)

You might be able to break down your responses into a series of small actions. For example, they all have a score they add (possibly 0,) a list of strings they randomly say, and each may or may not: kill you, destroy what you hit, … . So (this is C#, but same idea):

class responseType {
  int scoreChange;
  bool destroyObjectHit;
  int damageToObjecthit; // unused if destroyOH is true
  bool causesMyDeath;
  string[] randomResponses;
}

Then you just say score+=ReponseArray[responseMode].score; and so on. Any one-off stuff (like responseMode13 teleports, but nothing else ever will,) you can use the switch. In other words, the switch is only for a few weird things.

This would allow you to modify a respose, or “disable” it with an extra bool.