I'd love advice on the best path forward for implementing some custom interaction UI for my game.
I've made a prototype demonstrating the UI I'm looking for, and I'd love advice on the smartest way to make this work in an AC environment: https://fbetspizza.itch.io/catbox-prototype?secret=inJ58V3CZsVsu6EiVqWIOaHb8Uk
Just to explain the above, you begin the game with one skill, Journalism. This skill is a neon icon / glyph at the bottom of the screen that is default selected for you since this is your primary way of interacting with the world. The icon is also available at the bottom of the screen, hinting that there are many more possible ways of interacting with the world that are yet to be discovered. Clicking on these icons selects them and makes them your cursor.
When you click on something with this icon, you access the first level of journalism, which is merely giving you quick narration. If you hold down the mouse button over an object, the icon should glow and change—transforming—and then once it has transformed, if you release it, you will then access the second level of journalism, which is essentially fictional googling the object / person on your in-game phone and then being taken to a relevant webpage (note that in the prototype above, there are no transformation animation effects yet - it just changes icons after a few milliseconds). If you hold down the mouse button even longer over a person—holding it down until it transforms into a third icon and then stops transforming altogether—you are able to access the third level of journalism, which is actually talking to someone.
In the prototype above, you hold down your mouse button over the object, you should see the icon change between the various forms all the way to the third icon.
As you continue playing, you get more skills. For example, you may get the Bartending skill, as shown above. Skills you acquire may also have multiple levels, as shown above.
I'd love to know the best way to do this using AC. I'm looking for a high-level explanation of the steps I'd need to take. I'm guessing that to accomplish this, I'll need to replace the Interactions menu with something custom. Does it make sense to leverage the Inventory system for this? The only items that players are really collecting in the game are new player verbs/glyphs. Any pointers on how to do this in a smart, efficient and organized way would be greatly appreciated.
It looks like you're new here. If you want to get involved, click one of these buttons!
Comments
It's an interesting and unique interface, and I've had a bit of a think about the best approach. A bit of scripting will be necessary in any case, but shouldn't be too much.
Essentially it boils down to either the use of Interaction icons (as listed in the Cursor Manager), or the use of Inventory items. You'd be able to get it done with either, but from what you've described I'd say Inventory items are probably the better option.
As a top-level overview, I'm thinking:
The meat-and-bones of it will be in the custom interaction system. If you set the Interaction method to Custom Script, you can then rely on a script to handle exactly how and when Hotspot interactions get run.
The Manual's "Interaction scripting" and provided "Custom Interaction System Example" script should be your first ports of call, but essentially you'd want a script that:
KickStarter.playerInteraction.GetActiveHotspot ()
InvInstance.IsValid (KickStarter.runtimeInventory.SelectedInstance)
GlobalVariables.GetVariable ("SkillLevel").IntegerValue
KickStarter.runtimeInventory.SelectedInstance.Tex
KickStarter.playerInteraction.GetActiveHotspot ().RunInventoryInteraction (KickStarter.runtimeInventory.SelectedInstance.ItemID);
Thank you so much for giving this your thoughts, Chris. I really appreciate it. I absolutely love working with AC and I'm so grateful for your help.
I am going to reflect back what I understood from your instructions in terms of the steps I need to follow. Can you let me know if this is correct? Pardon the redundancy, I just want to make sure that I fully understand.
Is that right?
A few questions:
Re "Update the texture of the selected item." I just want to clarify that this is what will make my cursor change upon mousedown, right? Will I be able to then later add some sort of animation effect upon mousedown to make Glyph A somehow morph into Glyph B, or some other animation effect to let the player know that something is about to happen (like an animation around the cursor)?
Worth noting that in the game, you will acquire a skill like Bartending but only have Level 1, with Level 2 unlocked later when the player passes some milestone. Could that be made to work with the system above?
You mentioned that I could do this with either the Inventory system, or the Interaction icons. Is there any benefit you can think of to doing this with interaction icons before I commit to inventory system approach? Note that there will only be 10 skills or less you can acquire throughout the game.
This way of doing it requires writing a custom interaction system. One thing that's unclear to me is how easy it will be for a nontechnical narrative designer to add interactions to objects in scenes. Right now they know how to do basics like adding interactions using the inspector, and I'm hoping to keep it easy for them to do that. Will that still be possible? I think this relates to question #3 above.
Yep, sounds good.
You wouldn't need to attach the GameObject to any specific scene, however, as it won't make direct references to any specific objects. What you can do instead is attach it to a new Empty GameObject, make that a prefab, remove from the scene, and then run the Object: Add or remove Action to spawn it in when it each scene begins.
You can do this by hooking such an ActionList into the "Scene / Change / After" event in the Events Editor.
The cursor will change if the item's texture is updated - but it'll be down to the custom script exactly when that is.
If you want to rely on animation, however, you're not forced to go about it this way - you can instead just use Animator parameters with a Unity UI-based cursor. This could be automated by using an Integer parameter that's linked to the PopUp variable (by attaching the Link Variable To Animator component to your cursor's UI prefab).
Relying on a Unity UI prefab for your cursor is a case of setting your Cursor Manager's Cursor rendering to Unity UI. The New Game Wizard also includes an "Animated cursor" template you can play with to see how animations can be played on the cursor.
The Inventory Manager's Properties panel should be good for this - you can define a "Max skill" Integer, give each Item a starting value of 1, and then increase that at runtime through script. Item Property values can be modified at runtime, and will be stored in save-game files.
To get an API reference to the Item's Property, which can then be used in a script, right-click the field's label. This is possible for all Manager fields.
The use of properties as above is an advantage for the Inventory route. If it weren't for the skill level system, I'd have said go with the Interaction icon route - as clicking an icon and then using it with a Hotspot is already provided with Choose Interaction Then Hotspot mode.
Ultimately I can only make a good guess about the best route - it's really something you'd need to get in and try - but the custom script would be necessary in both cases, so the difference is more in the Editor (defining Inventory interactions vs Use interactions for Hotspots etc).
The interaction script would be a generic script that - aside from some visual extras - simply runs a given Hotspot interaction at the correct time, with the PopUp variable set to the correct value. A designer would not need to be involved - all they'd need to do is create the Inventory interaction for the Hotspot (per-skill), and use the Variable: Pop-up switch Action to split off the varying reactions based on which skill was used.
I was able to get it mostly working! However, I have one snag, and I'd love guidance. I'm having trouble with the GetActiveHotspot part of it. I am using v1.81.3 with 2022.3.8f1.
Here is a video of where it's at currently... almost working right: https://www.loom.com/share/1a49acb06ae44864b1997ac2594c8334?sid=e48a7d84-f2b3-4981-bead-f3c27ed0db4e
I've got my Global PopUp variable working for skill level, and I've created a new skill inventory box that includes Journalism (0 in the inventory manager) and Bartending (1). When I click on these glyphs and mouse down, I can cycle through different cursors. If I interact with objects that have the relevant Inventory interactions, the ActionList checks the PopUp Variable and currently plays different dialogue based on which cursor is selected/which level we're at.
Next, I want to make it so that the cursors only cycle when the mouse is hovering over a hotspot with relevant inventory interactions (like in the original prototype. Currently, I can cycle through interactions regardless of where my mouse is on the screen. However, for example let's say Lina Kim has a Journalism inventory interaction. When I hover my mouse over her, I should be able to cycle through the interactions and, upon releasing the mouse, perform the interaction. When I'm not over her, the cursor should revert to the default cursor.
In a perfect world, it would also be set up in such a way that it only cycles through the levels associated with a given object. Like you do Journalism 1, 2 and 3 on Lina, so it would cycle through all three. But let's say the cat only has Journalism 1 and 2. When I hover over the cat, I'd only be cycling between two cursors over it, not 3.
To begin solving at least the Skill part of it (I haven't gotten as granular as Skill level yet), I've tried detecting whether the relevant inventory interaction is present on a given hotspot, but I'm encountering a snag.
Here's my code that's actually working, as demonstrated in the video above: https://ctxt.io/2/AACYZlcYFg
And here's my failed attempt to get it working only when hovering over an object with a hotspot that has a relevant Inventory interaction: https://ctxt.io/2/AACYzo0pEw
When I run this, I get an error that's like "Checking interactions on hotspot: LinaKim for skill: Journalism, Result: False"
But this LanaKim game object definitely has the Journalism inventory interaction over it, so I'm not sure what I did wrong: https://imgur.com/a/5hXcwtl
Any idea what I'm doing wrong? Apologies if my code is a mess, I am new at this. Thank you again!
Looks good! Just a small tweak.
The HasRelevantInventoryInteraction function refers to the Hotspot's useButtons List, which contains the regular "Use" interactions that don't involve inventory.
You just need to have it instead reference invButtons, which is a separate List reserved for Inventory interactions:
This'll be possible - you'll just need a separate small script that you can attach to each Hotspot to set this data in. Something like:
You'd then just need to update your CustomInteractionSystem script to account for this. The code's a bit rough as it uses string literals, but this change to GetMaxSkillLevelForItem ought to do it:
Once you move the maxBartendingSkill etc values out of this script and into per-item Properties, you can then rely on the item ID values instead of strings.
That did it! It works flawlessly now. Thank you so much for your support, I am absolutely thrilled at the way my prototype is coming together. Huge fan of AC!