Hello Adventure Creator community;
In my seemingly never ending quest to make nice looking speech bubbles as my game's subtitle menus, I've been trying to write a custom action to move the speech menu child placements around -
The game has a lot of characters of varying sizes (like in the film Labyrinth, you might be talking to a big monster or a little caterpillar) that result in lots of varying degrees of camera zoom to frame them and the Player up nice. The subtitles being in the same places each time sometime results in bubbles off-screen or over the other character in the conversation.
So!
I tried to knock up a custom action so in a talking interaction I can nudge the X and Y of the speech menu placement around, like I can change those values in the editor at runtime to see the new positions.
I'm new to everything when it comes to coding (designer for decades) and the script below is ... not working ... when the change happens, the subs menu appears miles away from the scene, and the x and y values are nothing like the ones in the action.
Any hints? What am I doing wrong?
`
using UnityEngine;
using System.Collections.Generic;
using UnityEditor;
namespace AC
{
[System.Serializable]
public class ActionChangeSpeechChildPos : Action
{
// Declare variables here
public GameObject speakingCharacter;
public float childX;
public float childY;
public int constantID;
override public void AssignValues()
{
speakingCharacter = AssignFile(constantID, speakingCharacter);
}
public ActionChangeSpeechChildPos()
{
this.isDisplayed = true;
category = ActionCategory.Character;
title = "Change Speech Position";
description = "Change the speech child object position for this character";
}
public override float Run()
{
/*
* This function is called when the action is performed.
*
* The float to return is the time that the game
* should wait before moving on to the next action.
* Return 0f to make the action instantenous.
*
* For actions that take longer than one frame,
* you can return "defaultPauseTime" to make the game
* re-run this function a short time later. You can
* use the isRunning boolean to check if the action is
* being run for the first time, eg:
*/
{
if (speakingCharacter)
{
speakingCharacter.transform.position = new Vector3(childX, childY, speakingCharacter.transform.position.z);
}
return 0f;
}
}
public override void Skip ()
{
/*
* This function is called when the Action is skipped, as a
* result of the player invoking the "EndCutscene" input.
*
* It should perform the instructions of the Action instantly -
* regardless of whether or not the Action itself has been run
* normally yet. If this method is left blank, then skipping
* the Action will have no effect. If this method is removed,
* or if the Run() method call is left below, then skipping the
* Action will cause it to run itself as normal.
*/
Run ();
}
#if UNITY_EDITOR
public override void ShowGUI ()
{
speakingCharacter = (GameObject)EditorGUILayout.ObjectField("Speech Child Object", speakingCharacter, typeof(GameObject), true);
childX = EditorGUILayout.FloatField("New child X position:", childX);
childY = EditorGUILayout.FloatField("New child Y position:", childY);
constantID = FieldToID(speakingCharacter, constantID);
speakingCharacter = IDToField(speakingCharacter, constantID, true);
AfterRunningOption ();
}
public override string SetLabel()
{
// Return a string used to describe the specific action's job.
if (speakingCharacter)
{
return ("Change + speakingCharacter.name ");
}
return "";
}
}
}
`
It looks like you're new here. If you want to get involved, click one of these buttons!
Comments
The code looks all right, but it's a case of what exactly you want it to do.
Right now, you're controlling the position in world-space, so it'll always be placed in the same position no matter where the character is standing. It may be that you instead want to affect the local position instead.
Here's a modified script that'll do that:
That's great! The local transform was what I was missing, thanks!
There's one more thing though ... The script was put together following this tutorial https://adventurecreator.org/tutorials/writing-custom-action-2 and afaict, should work with my Player prefab, so long as their speech placement child has a ConstantID assigned to it. However, dragging that gameobject into the action, whether from the prefab or an in-scene instance of the Player, doesn't cause the ConstantID to register in the action, and the ID itself doesn't appear in the GUI.
Can you spot anything in the ConstantID part that might be causing this, or do I need to jury rig an Is Player? tick-box from one of the other actions?
The Constant ID component has "Retain in prefab?" checked? Try dragging it into the Action from Prefab Mode.
Though, you can always add an "Is Player?" checkbox to the Action, to automatically assign it:
Thanks Chris!
For anyone playing along at home, dragging the speech child (with ConstantID componet) onto the action from prefab mode doesn't work for me - but, the isPlayer tickbox in the code above works a treat!
It's gonna look so good, we're very grateful!