+2
Planned

Proposals for GC2.0

Martin 3 months ago in Game Creator updated 2 months ago 6

Hi,

with you being busy creating Traversal and all, I'd like to propose some ideas we (me and some colleagues and students) have collected over time, also having tried out several other Trigger-Action-Condition based systems and also having talked to several developers from established companies (like Deck13, Ubisoft, CryTek) as well as indie devs.

So here are the points, roughly sorted by the priority we feel they have:

- ScriptableObject based approach for all Actions/Triggers/Conditions instead of Monobehaviour. 
Generally putting Monobehaviors on empty GameObjects just to have them in a scene doesn't feel right. GameObjects have a Transform and represent things that have a position in 3D space and are part of a visible scene. So having an empty GO as a point to spawn gun muzzle is ok, but putting a GameManager etc. into a scene just cannot be right. It would be a much cleaner design. This would also make scene-independent logic possible. The behavior module is already doing this.

- Blackboard-based approach for all variables. Every field of an Action/Condition can by-default be populated with a variable value from a blackboard. This is kind-of implied by the ScriptableObject-based approach, that cannot directly reference GameObjects in the hierarchy. 

- Remove the naming confusion between "Actions" (an Actions-Object), Actions (the plural of one Action), and Action (one single Action):
     -> "Conditions" should be more generally called FlowControl-Nodes or FlowControl-Objects, so all the nodes that somehow define the flow can be in this category, not only If-Then-Else but also switch and branch nodes of all kind.
     -> An Actions-Object should be called "ActionSequence". Because it is a container class and that name is very intuitive.
     -> One graph containing Triggers, ActionSequences and FlowControls could be called a "Flow"

- Provide a node-based tool to arrange the nodes of a Flow-Graph visually. This works well, as a Flow usually does't contain too many Actions. An ActionSequence can be a single node that is expandable, like the inspector view now, but in a graph-node.

- Have some powerful FlowControls by default, like a weighted random selection of one (or more!) ActionSequence (with options of, e.g., never selecting twice) with weights being modifiable at runtime, and also potentially multiple ActionSequences being picked for execution. Such stuff can be extremely important for story-driven games and dialog-logic.

- Have an Action that waits for an event (like a trigger in the middle of a sequence). This makes powerful synchronization between Flows possible.

So these are the distilled points that came up over time and from lots of hours of collaborative thinking and using such systems.

I hope this can help make Game Creator even greater and introduce and establish this fantastic approach to an even broader community.

with best regards

Martin

Unity version:
Game Creator version:
2.0
+2

It could be good to introduce the new actions and improve existing actions related with transforms, rotations, physics and using of variables in the Actions.

1. Actions to get / set X, Y, Z components of Vector3 variable independently from/to the Global/Local variables.
2. Set values of Number and Bool variables from the variables.
3. New action which set Transform.eulerAngles of Player, Character, Object or Invoker to the Vector3 variable.
4. Improve Transform, Transform Rotate, Transform Rotate Towards actions extending them with possibility to set Rotation angle values (Euler Angles) from the Global / Local variables (related with the previous suggestion).
5. Extend Rigidbody action with Drag and Angular Drag parameters.
6. New action Velocity which store Velocity Magnitude of Rigidbody of Player, Character, Object or Invoker to the Number variable.

+1

Thanks! The current problem with Actions is requires a bit cumbersome work for each new Action to be made, including setting up a new icon. This is something I definitely want to improve as creating a custom Action should be fast so I can more quickly produce them.

Among this, now that I have a better understanding of the Game Creator ecosystem, I'll be able to better organize the list of Actions, Conditions, etc.. in more categories. Plus, the new syntactic-error tolerant finder will make it much faster and easier to find the correct Action.

So expect all(most) these ideas to be in Game Creator 2.0 :-)

+2
Planned

Thanks Martin for the ideas! It looks like you've put a lot of thought into this and I really appreciate it :-) Let me comment some points as there are some I completely agree and there are others I'd like to discuss further.

- ScriptableObject based approach for all Actions/Triggers/Conditions instead of Monobehaviour.
Generally putting Monobehaviors on empty GameObjects just to have them in a scene doesn't feel right. GameObjects have a Transform and represent things that have a position in 3D space and are part of a visible scene. So having an empty GO as a point to spawn gun muzzle is ok, but putting a GameManager etc. into a scene just cannot be right. It would be a much cleaner design. This would also make scene-independent logic possible. The behavior module is already doing this.


I'll comment along the next point.

- Blackboard-based approach for all variables. Every field of an Action/Condition can by-default be populated with a variable value from a blackboard. This is kind-of implied by the ScriptableObject-based approach, that cannot directly reference GameObjects in the hierarchy.

Originally, this was the idea. However, as you say, it requires a Blackboard as a proxy between scene objects and the action scriptable objects. I didn't like this because you'd have to constantly go back and forth between the game object with the Blackboard scene front and the Action's Blackboard.

However, with the introduction of Unity's polymorphic serialization, this is no problem at all: Actions will not need to be bound to a game object anymore. This is one of the biggest changes and the main reason I want to develop Game Creator 2: This will allow to have Actions on scriptable objects, game objects, Formulas, characters, weapons, ... Basically any script that is a class-type.

- Remove the naming confusion between "Actions" (an Actions-Object), Actions (the plural of one Action), and Action (one single Action):
-> "Conditions" should be more generally called FlowControl-Nodes or FlowControl-Objects, so all the nodes that somehow define the flow can be in this category, not only If-Then-Else but also switch and branch nodes of all kind.
-> An Actions-Object should be called "ActionSequence". Because it is a container class and that name is very intuitive.
-> One graph containing Triggers, ActionSequences and FlowControls could be called a "Flow"

There's some tech debt here that I've been wanting to address and naming is one of them. The Actions is maybe the one that causes highest confusion, because Actions is a component that contains a list of Action(s), and it's hard to distinguish between the component name and the plural. That's why Game Creator 2 you will have an Actions component that has an InstructionList, which contains a list of Instructions.

There will be some other name changes that make more sense. For example, I'm leveraging the idea of changing the Camera Motor name into Camera Shots. I believe the term "shot" makes much more sense. Triggers will have Events that fire them (right now they are called Igniter, which is a cool name, but not that good). To be honest, one of my struggles is finding that perfect name for each feature :-D

- Provide a node-based tool to arrange the nodes of a Flow-Graph visually. This works well, as a Flow usually does't contain too many Actions. An ActionSequence can be a single node that is expandable, like the inspector view now, but in a graph-node.

Comment along the next point

- Have some powerful FlowControls by default, like a weighted random selection of one (or more!) ActionSequence (with options of, e.g., never selecting twice) with weights being modifiable at runtime, and also potentially multiple ActionSequences being picked for execution. Such stuff can be extremely important for story-driven games and dialog-logic.

This is the point I'm not sure about. I may be a bit biased as by OCD usually kicks, but I've never liked graphs. They look good on paper but in real production environments tend to end up as a spaghetti mess and makes it hard to iteratively work on a project. The only exception for me are Behavior Graphs, which make sense, but they are also very restrictive in terms of how they can connect to each other and it's impossible to visually have an edge passing over another one.

However, I see many people liking graphs. Not something I worry about, because a tool like this could be easily built on top of the Actions. It wouldn't require to make specific code on the core to make it work, so it's something that can be added later.

- Have an Action that waits for an event (like a trigger in the middle of a sequence). This makes powerful synchronization between Flows possible.

Hah! This is something that's already possible but I haven't made any examples yet. There's the "On Receive Event" Trigger that listen for a named event to happen. You can fire events using the "Send Event" Action. It's highly optimized, although it uses string comparison at the moment, but this is something I will address sooner or later.

Thanks for the ideas! Please feel free to comment them or add any more suggestions.

+3

Hi Marti, 

wow, that was a very cool and detailed answer and it makes me feel more than positive about GC2.0 being a revolutionary step for Unity devs. Allow me me to address your points:


- However, with the introduction of Unity's polymorphic serialization, this is no problem at all: Actions will not need to be bound to a game object anymore. This is one of the biggest changes and the main reason I want to develop Game Creator 2: This will allow to have Actions on scriptable objects, game objects, Formulas, characters, weapons, ... Basically any script that is a class-type.

So, if I understand correctly, Actions-Objects themselves will be ScriptableObjects that can be (polymorphically) referenced by any other object? And these SOs can in-turn reference other things like GameObjects or Monbehaviours.

That sounds like a great idea to use this new Unity feature.

How do you envision the workflow when creating a new set of Trigger, Actions, and Conditions (which I think should be a single ScriptableObject called a Flow or FlowGraph)? Could you elaborate on your envisioned architecture?

- There's some tech debt here that I've been wanting to address and naming is one of them. The Actions is maybe the one that causes highest confusion, because Actions is a component that contains a list of Action(s), and it's hard to distinguish between the component name and the plural. That's why Game Creator 2 you will have an Actions component that has an InstructionList, which contains a list of Instructions.There will be some other name changes that make more sense. For example, I'm leveraging the idea of changing the Camera Motor name into Camera Shots. I believe the term "shot" makes much more sense. Triggers will have Events that fire them (right now they are called Igniter, which is a cool name, but not that good). To be honest, one of my struggles is finding that perfect name for each feature :-D

I think its a good idea to unify the naming that each trigger has an Event-field. As far as I can see it was called Igniter only in the code but not in the UI of a Trigger.

In general, I think it is a good and clean practice to name container classes not with the plural (like "Actions" or "Enemies") but like in many frameworks and languages as a concatenation of the type it contains and the underlying data structure. Examples are "EnemyQueue" or "PlayerList". In this spirit, I think an Actions-Object should not be called "Actions" anymore but since it is really a set of actions that are sequentially executed, it is an "ActionSequence". Sorry for repeating, but I'm convinced that a clear and consistent nomenclature can make GC significantly stronger. Using terms like "InstructionList" only introduces the new term "instruction", which is usually associated with a low-level programming approach, where GC positions itself as a high-level visual scripting environment (more on "high-level" later). Therefore, I strongly believe that it is utmost important to keep naming simple and not introduce even more terms.

Also I think the term "Condition" is a bit too narrow, and I think a "FlowControl" is more appropriate. We already had thought of getting rid of these Conditions/FlowControls entirely and just make them a type of action that happens to branch.

- This is the point I'm not sure about. I may be a bit biased as by OCD usually kicks, but I've never liked graphs. They look good on paper but in real production environments tend to end up as a spaghetti mess and makes it hard to iteratively work on a project. The only exception for me are Behavior Graphs, which make sense, but they are also very restrictive in terms of how they can connect to each other and it's impossible to visually have an edge passing over another one. However, I see many people liking graphs. Not something I worry about, because a tool like this could be easily built on top of the Actions. It wouldn't require to make specific code on the core to make it work, so it's something that can be added later.

I fully agree that this could be developed as an additional module and could be done later.

However, let me tell you that I am a coder myself for my whole life, and I think visual scripting is a plain wrong approach. The nodes of such a graph are helpless spaghetti (and I even disallow this kind of scripting for my students), because it is a fundamentally wrong approach to try and mimic programming with a programming language using visual nodes. However, during the last years seeing many project teams work together with game-designers, story-writers, vfx-artists, and others, it is stunning what such a tool can do for the team success, if it is high-level. The tasks (actons) should never be on the level of a programming language instructions, but in terms of higher level design-thinking. And GC is already going this approach. This means in turn that the resulting graphs will be relatively small and not branch a lot (no spaghetti) because a graph of Trigger-ActionSequence (containing some FlowControls for branching) is pretty sequential in its nature. It is an extremely successful way for students and indie teams to work together in such a way, having the effect that the coder doesn't become the bottleneck when he has to implement the story and high-level game logic. So in summary, I really don't like graphs, but I've experienced first-hand over long years that high-level visual scripting is extremely successful.

I also cannot overstate how useful some powerful FlowControls by default allowing story-writers and puzzle-designers for intertwining story-driven content and dialog-logic.


- Hah! This is something that's already possible but I haven't made any examples yet. There's the "On Receive Event" Trigger that listen for a named event to happen. You can fire events using the "Send Event" Action. It's highly optimized, although it uses string comparison at the moment, but this is something I will address sooner or later.

Ah, yes. I saw that in the documentation and that's really useful. But what I meant here is not an "On Receive Event" Trigger but a "Wait for Event" Action. That is very simple to implement but allows us to synchronize between running ActionSequences.



Thanks for discussing such stuff openly with the community. From what I have experienced in the last years I'm fully convinced that such an attitude and these things discussed here can make GC a complete must-have for any projects, and I will try to convince my Unity contacts that they need to pursue this high-level path, as opposed to just buying and integrating Bolt visual scripting.

+1

Thanks! Sorry for the late reply, but I've saved some threads I want to take the time to put my full attention, like this one.

Right now I'm fully focused on the Traversal module and updating all current modules, so I'm saving this thread to fully develop once the current GC generation is updated.

Despite this, let me comment on a couple of things:

Regarding polymorphic serialization:

So, if I understand correctly, Actions-Objects themselves will be ScriptableObjects that can be (polymorphically) referenced by any other object? And these SOs can in-turn reference other things like GameObjects or Monbehaviours.

That sounds like a great idea to use this new Unity feature.

How do you envision the workflow when creating a new set of Trigger, Actions, and Conditions (which I think should be a single ScriptableObject called a Flow or FlowGraph)? Could you elaborate on your envisioned architecture?

Not really. Right now if you have something like:

class IAnimal {}

class Cat : IAnimal {}

class Dog : IAnimal {}

And you create an array of type IAnimal:

public IAnimal[] animals = { new Cat(), new Dog() };

Unity will serialize this as a sequence of IAnimals, instead of the particular type of each one (Cat and Dog). To overcome this, GC1 makes each "Cat" and "Dog" classes inherit from MonoBehaviour, which supports polymorphism... But restricts its use to scene objects and prefabs.

However, there's a new way to do this which basically will allow to declare an array of generic elements and correctly serialize them as concrete classes.

What all this blah-blah means is that you can have Actions (aka Instructions) bound to anything: Unity components, scriptable objects, custom classes, ... Anything!

I'll give more details and examples once I start developing this, so it's easier to understand.

---

Regarding the naming conventions, I'm still looking at alternatives, but I don't really like compound names unless the first name is used for something else and related. For example, I don't like the idea of naming "ActionsSequence" when there's no "Actions" first. This is a personal thing (see how all modules are named with a single word).

However, there's another reason why ActionsSquence wouldn't fit right, and that is because from the programming perspective, the data layout will be:

Actions => contain InstructionList => contain array of Instruction

Naming ActionsSequence would be confusing when there's already a InstructionList.

Despite this, I'm still changing the nomenclature here and there and trying new things, so everything is still in mock-up stage. Thanks though for taking the time and thought you've put into this! Feel free to give us more ideas/suggestions. Really appreciate them

+1

Hi Marti,

I understand that Traversal is now the full priority. No worries.

Regarding the nomenclature, I agree that Event instead of Igniter is more intuitive and designer-friendly.

However, if you start breaking Actions down into Instructions and InstructionLists you get one step closer to a low-level visual scripting system and the great high-level and designer-friendly terminology and approach are somehow compromised. Instructions sound much more like lines of code that "Actions".

I still think that Action and ActionSequence (singular+sequence) is most appropriate and most intuitive to understand for humans except coders (game designers, story writers, artists, etc.).


What I saw when browsing through the source code of GC core, is that the folder for the core classes (like IAction) is called "ScriptableObjects" :) ... so at one point you must have already thought about it.

- Martin