Forum rules - please read before posting.

Prefab Conversation doesn't work with Parameters?

edited December 2018 in Technical Q&A

I'm encountering a really strange problem with Prefab Conversations.

At start of the scene I instantiate some prefab characters. The Conversation is not currently instantiated, just sits in the scene, but: it's made into a prefab, has Remember Conversation script (and retain in prefab? checked), also I'm using Sync Conversations script from the wiki page.

When character is instantiated and you click on him, I run an ActionList from Asset File. The ActionList has one parameter called Character. At the start of ActionList I run ActionList:Set Parameter and I drag in a character prefab.

Next Action is simple Play Speech and when parameter is used everything is fine. There's also Move To Point just to make sure everything works.

When I introduce my prefab Conversation, the parameter doesn't work past the conversation - in Play Speech the dialog option appears to be like narrative (when you don't assign a character to Speech) and Move To Point doesn't do anything. If I use custom action I get Null Pointer Reference. I don't think it's the character prefab that's the problem, because everything behaves the same even with normal character that's in scene.

However, if I Set Parameter again, after the conversation, everything works once again.

Similarly, it works fine if I don't use parameters after the conversation, and if I just re-assign the character by hand.

Here's the Conversation object - it sits in the scene.

I have no idea what's going on here, but definitely looks like something's up with the Conversation object, just can't quite nail down what it is. As a workaround I can just keep re-assigning the character parameter after each conversation, but ideally I would just do it once at the start of the ActionList. Am I doing something silly once again?

Comments

  • Thanks for the clear explanation of the issue.

    No, everything looks fine - at least so far as you've described. It's not clear what the issue is, and I suspect it won't be so until I've seen it for myself.

    If you can create a .unitypackage file of the scene, the Conversation and NPC prefabs, and the ActionList assets involved, PM it to me and I'll attempt a recreation.

  • This is due to the way the Override options? option in the Dialogue: Start Conversation Action works, in that it causes the ActionList to stop and re-start from that point rather than pause.

    When you use the ActionList: Set parameter Action to modify an ActionList asset's own parameters, you're modifying that of the single instance of that ActionList at runtime - not the original asset itself. This is so because multiple instances of an asset can be run - each with their own parameter values.

    When the Conversation is started, the ActionList is stopped - and then re-started when the Player chooses an option, which causes the parameter values to take on the values of the ActionList asset.

    This is why re-assigning the parameter value after the Conversation works. You could also get around it by assigning the ActionList asset at the start as well. However, there is a cleaner solution that involves a tiny bit of custom scripting.

    Since the ActionList in question is a Hotspot Interaction, and contains a GameObject parameter, the Hotspot Inspector allows you to set that parameter value to be the Hotspot's GameObject automatically. If it was attached to the NPC's root - you'd be set - but as it's on a child object you just need a simple script to change the set parameter's value to that of the parent:

    http://pasteall.org/1438067/csharp

    Attach that as a component in your scene, and assign the ActionList asset and parameter ID in its Inspector. You should then get a message when the ActionList runs, telling you that this parameter value has been changed to its parent. You can then remove the ActionList: Set parameter Actions in your ActionList.

  • I have set Hotspot parameter to Character (0) in the Inspector (for the child object), and then assigned the component with the script to the parent object. I removed the ActionList: Set parameter and everything works great now.

    Thank you for the explanation of the problem and for going through the trouble to test my scene! I really appreciate it!

  • Hi,
    I played around with this a bit further, and there's a small problem. I added the Script component (your code) to the NPC (parent, but also tested with child object).

    I have a scene set up like this:
    2 Characters both with the script and both lead to the same ActionList, which is simply Dialgoue: Play Speech. The Action is set to use parameter 0.

    If you click on Character1, then Character2 plays the line. If you click Character1 again and again, then he plays the line as he should thereafter. And then if you click the Character2, Character1 plays the line and if you click Character2 again he works as normal. I hope that makes sense.

    The debug log (from the script) states the correct name of the clicked character though, so it's likely I'm messing something up in the set up...

  • Hi, sorry for triple posting but I still have some trouble with the code.

    What I'm trying to do is to use the parameter code to get the correct character talking.

    The Parent object of the NPC has the code component:

    The child of the NPC has the parameter set up:

    It all links to the same ActionList with only One Speech set up:

    I have second NPC set up exactly the same way and they both link to the same ActionList. I would like to have the same ActionList working with two (or more) different characters, so whichever character you click on, that character will say the line.

    It works... Partially. Here's what I mean:

    It seems that the code Set Param Parent works and detects which character you clicked on, but the speech is happening before the new character is set as a parameter resulting in some kind of "lag". Ideally what would happen is that the character you clicked on would say "123" straight away. I've played around with it for hours, but no success. Any help greatly appreciated!

  • Only one instance of the script needs to be present in the scene - the code is generic. Remove it from your NPCs, and try placing just a single instance of it on a fresh empty GameObject.

    Since pasteall.org is currently down, here's the code again (for the benefit of others viewing this thread):

    using UnityEngine;
    using System.Collections;
    using AC;
    
    public class SetParamChild : MonoBehaviour
    {
    
        public ActionListAsset actionListAsset;
        public int parameterID;
    
    
        private void OnEnable ()
        {
            EventManager.OnBeginActionList += OnBeginActionList;
        }
    
    
        private void OnDisable ()
        {
            EventManager.OnBeginActionList -= OnBeginActionList;
        }
    
    
        private void OnBeginActionList (ActionList _actionList, ActionListAsset _actionListAsset, int startingIndex, bool isSkipping)
        {
            // Just run an ActionList, check it's the right one
            if (actionListAsset != null && _actionListAsset == actionListAsset)
            {
                // Correct ActionListAsset, so modify its parameters
                ActionParameter parameter = _actionList.GetParameter (parameterID);
    
                // Make sure this is a GameObject parameter
                if (parameter != null && parameter.parameterType == ParameterType.GameObject)
                {
                    // Extract the current GameObject value
                    GameObject currentGO = parameter.gameObject;
                    if (currentGO != null && currentGO.GetComponentInChildren <Animator>())
                    {
                        // Get the child GO with an Animator on it
                        GameObject newGO = currentGO.GetComponentInChildren <Animator>().gameObject;
    
                        // Re-assign the parameter value to this new GO
                        parameter.gameObject = newGO;
                    }
                }
            }
        }
    
    }
    
  • edited January 2019

    I removed the script from the NPC's, and placed it on a fresh empty GameObject. I dragged the ActionList onto the script:

    The child object of the NPC has his interaction set up like this (2 different NPCs have the same interaction):

    When I click on the ActionList during runtime (asset in the folder), the Dialogue:Play speech looks like this:

    Currently, no one is saying the dialogue line, as the speaker is not assigned. Am I missing something?

    I've also tried changing GetComponent Animator to ConstantID but no luck.
    The code seems a bit different than the last one, and if I use the last code on a new GameObject, then it works, but same issue as my previous post.

    Here's the previous code:
    `
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using AC;

    public class SetParamParent : MonoBehaviour
    {

    public ActionListAsset actionListAsset;
    public int paramIDToSetAsParent;
    
    private void OnEnable()
    {
        EventManager.OnBeginActionList += OnBeginActionList;
    }
    
    private void OnDisable()
    {
        EventManager.OnBeginActionList -= OnBeginActionList;
    }
    
    private void OnBeginActionList(ActionList actionList, ActionListAsset actionListAsset, int startingIndex, bool isSkipping)
    {
        if (this.actionListAsset == actionListAsset)
        {
            ActionParameter parameter = actionListAsset.GetParameter(paramIDToSetAsParent);
    
            if (parameter.gameObject != null && parameter.gameObject.transform.parent != null)
            {
                parameter.gameObject = parameter.gameObject.transform.parent.gameObject;
    
                if (parameter.gameObject.GetComponent<ConstantID>())
                {
                    parameter.intValue = parameter.gameObject.GetComponent<ConstantID>().constantID;
                }
                else
                {
                    parameter.intValue = 0;
                }
    
                Debug.Log("Set parent parameter of " + actionListAsset + " to " + parameter.gameObject);
            }
        }
    }
    

    }
    `

    EDIT:
    Sorry if the code is displaying a bit funky. pasteall.org is down and I can't seem to edit the code on the forum correctly.

  • The script relies on the parameter being set before the ActionList is run - so that it can then convert that parameter GameObject into its child.

    You shouldn't have to change the script, but it won't work if you're running the ActionList manually - since it's only when interacting with the Hotspot that the parameter is originall set.

    Currently, no one is saying the dialogue line, as the speaker is not assigned. Am I missing something?

    From the way you've worded this, I'm not sure if you're only attempting to run the ActionList manually via the Inspector. Are you getting this result when interacting with the Hotspot? If so, more Debug.Log statements within the script may help learn the issue, i.e. before the second "if" statement:

    Debug.Log ("Parameter: " + ((parameter != null) ? paramater.label : " None found!"));
    
  • I'm triggering the ActionList from the hotspot (NPC -> Hotspot Script -> Use Interactions). That ActionList has parameter 0 set as "Character".

    I've added the Debug line before the second "if" statement and in Console it says: "Parameter: Character". I also added another line Debug.Log("Parameter Name:" + parameter.gameObject.name); and it returns "Parameter Name: Peasant". When you click on different character, then it returns that character's name.

    So it seems like it's working fine, but the Dialogue: Play speech action (which is set to Speaker -> Character (0)) doesn't work and it just plays the dialogue line in top left corner of the screen.

    It seems that the parameter is set AFTER the ActionList has already been triggered.

  • The event is set to run before any Actions within the ActionList are triggered. Does the last Debug.Log statement (the one in the last script you posted) get shown?

    What are your AC/Unity versions now? This works fine for me.

  • Yes, it gets shown.

    Its possible that I've set it up not correctly.
    Would you be able to give me quick rundown of how it needs to be set up?

    My versions:
    Unity Version: 2018.2.18f1
    AC Version: 1.65.2
  • I see it now. The problem is that you are updating the parameters of the ActionListAsset, not the ActionList - which is what's actually being run.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using AC;
    
    public class SetParamParent : MonoBehaviour
    {
    
        public ActionListAsset actionListAsset;
        public int paramIDToSetAsParent;
    
        private void OnEnable()
        {
            EventManager.OnBeginActionList += OnBeginActionList;
        }
    
        private void OnDisable()
        {
            EventManager.OnBeginActionList -= OnBeginActionList;
        }
    
        private void OnBeginActionList (ActionList actionList, ActionListAsset actionListAsset, int startingIndex, bool isSkipping)
        {
            if (this.actionListAsset == actionListAsset)
            {
                ActionParameter parameter = actionList.GetParameter (paramIDToSetAsParent);
    
                if (parameter.gameObject != null && parameter.gameObject.transform.parent != null)
                {
                    parameter.gameObject = parameter.gameObject.transform.parent.gameObject;
    
                    if (parameter.gameObject.GetComponent<ConstantID>())
                    {
                        parameter.intValue = parameter.gameObject.GetComponent<ConstantID>().constantID;
                    }
                    else
                    {
                        parameter.intValue = 0;
                    }
    
                    Debug.Log ("Set parent parameter of " + actionListAsset + " to " + parameter.gameObject);
                }
            }
        }
    
    }
    
  • Yesssssss, everything is working fine now!

    Thank you so much for the help and the patience!

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.