Forum rules - please read before posting.

Getting a custom action to work with parameters

Hi fellow creators! Happy new year!!!
I just came back to my adventure after the holidays and I am having some difficulty trying to get my custom action to work with parameters. I have already tried the tutorial on the website, no problem with that, but I need to create another action with a different functionality. Maybe the answer is very simple.
I created a CloseUp menu that is meant to activate automatically when player clicks on inventory objects. It has its own dedicated label, description and close up image. I created animation clips to control the image to display, and I created a custom action "Change Text" in order to display the corresponding description.
So far, so good, but the next step is to create a generic ActionList with parameters, so I don't have to recycle the same steps every time an inventory item is interacted with. It would be something like this:
1. Turn on close up menu.
2. Change Label Text for parameter 0
3. Change Description Text for parameter 1
4. Change animation clip for parameter 2
(all 3 parameters are strings)
So I need to go back to my Change Text script, which I based on the custom action tutorial with a few changes of my own, and make it work with parameters. And this is where I can't extrapolate the script from the Use Gravity example in order to make it work with my custom action.

Just to show you what I have, this is the main body in my Change Text script without any of the code for using parameters.

        override public void AssignValues()
        {
            objectToAffect = AssignFile(constantID, objectToAffect);
        }

        override public float Run ()
        {

            objectToAffect.GetComponent<Text>().text = newText;


            if (!isRunning)
            {
                isRunning = true;
                return defaultPauseTime;
            }
            else
            {
                isRunning = false;
                return 0f;
            }
        }


        override public void Skip ()
        {

             Run ();
        }


        #if UNITY_EDITOR

        override public void ShowGUI ()
        {
            // Action-specific Inspector GUI code here

            objectToAffect = (GameObject)EditorGUILayout.ObjectField("GameObject to affect:", objectToAffect, typeof(GameObject), true);


            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Text:", GUILayout.Width(65f));
            EditorStyles.textField.wordWrap = true;
            newText = EditorGUILayout.TextArea(newText, GUILayout.MaxWidth(400f));
            EditorGUILayout.EndHorizontal();



            constantID = FieldToID(objectToAffect, constantID);
            objectToAffect = IDToField(objectToAffect, constantID, true);

            AfterRunningOption();
        }



        #endif

    }

}

Any help would be appreciated!!! Thank you in advance!

Comments

  • edited January 2

    Have you been through the parameters tutorial? I'd like to know where it wasn't clear so that I might improve things.

    Parameters work by creating a reference to the parameter's ID, which is then used to update the original field's value (in this case, "newText"). If set to -1 (the default), no override will take place.

    As your Action only requires one Run call, you can also simply return 0f without having to do a check for isRunning. The Skip function can be removed as well, since this will call Run by default.

    Try this:

    public int newTextParameterID = -1;
    
    override public void AssignValues (List<ActionParameter> parameters)
    {
        objectToAffect = AssignFile (constantID, objectToAffect);
        newText = AssignString (parameters, newTextParameterID, newText);
    }
    
    override public float Run ()
    {
        objectToAffect.GetComponent<Text>().text = newText;
        return 0f;
    }
    
    #if UNITY_EDITOR
    
    override public void ShowGUI (List<ActionParameter> parameters)
    {
        objectToAffect = (GameObject)EditorGUILayout.ObjectField("GameObject to affect:", objectToAffect, typeof(GameObject), true);
        constantID = FieldToID(objectToAffect, constantID);
        objectToAffect = IDToField(objectToAffect, constantID, true);
    
        newTextParameterID = Action.ChooseParameterGUI ("Text:", parameters, newTextParameterID, ParameterType.String);
        if (newTextParameterID < 0)
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Text:", GUILayout.Width(65f));
            EditorStyles.textField.wordWrap = true;
            newText = EditorGUILayout.TextArea(newText, GUILayout.MaxWidth(400f));
            EditorGUILayout.EndHorizontal();
        }
    
        AfterRunningOption ();
    }
    
    #endif
    

    You'll also need to include the following at the top, since this uses Lists:

    using System.Collections.Generic;
    
  • Hi Chris! Thank you so much for your quick answer! I will try that now. Yes, I tried the tutorials (that's where I got most of the code from, which I adapted from the Use gravity action), but my grasp of coding it is still very rudimentary, so I couldn't think my way through it, since I didn't know about the AssignString method. The rest, I think I can wrap my head around.
    I'll run this and come back to mark this as solved. Thanks again and happy 2020!!!

  • This worked!
    When it comes to the tutorial, I can only speak from my own perspective, but if it helps, maybe it would have been more clear to me with a few more examples with assets + parameters, where the parameters you pass are of types other than GameObjects.

  • I have an additional question about this. This is working, but somehow something strange happens in the ActionList editor. The two actions that change my CloseUp menu texts are linked to two UI text prefabs. When I enter play mode everything works fine, but after exiting, the two prefabs are missing in the ActionList editor (the constantID is still there, though), and functionality is preserved in gameplay. The editor says "further controls cannot display because the referenced object cannot be found", but if I re-reference the two assets, all the data is there. Is this how it's supposed to be? I don't have any problems now, but I am worried it may create trouble at some point.
    I am attaching how the ActionList Editor looks before, during and after gameplay. Image here.
    This happens whether I am passing parameters or not.
    Please let me know if you have any ideas. Thanks in advance!

  • The error message can be hidden by passing the last parameter in the IDToField function as false, i.e:

    objectToAffect = IDToField(objectToAffect, constantID, false);
    

    The de-linking of fields after exiting playmode is something I've fixed for the official Actions, and it typically involves separating the "runtime" GameObject you affect from the one you assign in the GUI.

    i.e.:

    public int newTextParameterID = -1;
    private GameObject runtimeObjectToAffect;
    
    override public void AssignValues (List<ActionParameter> parameters)
    {
        runtimeObjectToAffect = AssignFile (constantID, objectToAffect);
        newText = AssignString (parameters, newTextParameterID, newText);
    }
    
    override public float Run ()
    {
        runtimeObjectToAffect.GetComponent<Text>().text = newText;
        return 0f;
    }
    
    #if UNITY_EDITOR
    
    override public void ShowGUI (List<ActionParameter> parameters)
    {
        objectToAffect = (GameObject)EditorGUILayout.ObjectField("GameObject to affect:", objectToAffect, typeof(GameObject), true);
        constantID = FieldToID(objectToAffect, constantID);
        objectToAffect = IDToField(objectToAffect, constantID, false);
    
        newTextParameterID = Action.ChooseParameterGUI ("Text:", parameters, newTextParameterID, ParameterType.String);
        if (newTextParameterID < 0)
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Text:", GUILayout.Width(65f));
            EditorStyles.textField.wordWrap = true;
            newText = EditorGUILayout.TextArea(newText, GUILayout.MaxWidth(400f));
            EditorGUILayout.EndHorizontal();
        }
    
        AfterRunningOption ();
    }
    
    #endif
    
  • Got it. Running smoothly now :)

    Thanks a lot.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.