playMaker

Author Topic: Get Property & Add Script -or- how to access script based on string  (Read 1716 times)

Thore

  • Sr. Member
  • ****
  • Posts: 341
    • View Profile
Hello :)

The Issue
I can easily add a script to an object by name (with the "Add Script" action), but then I find no way to access this script for further use, (for example with Get/Set Property). How can I access the script attached?

When I want to reference it, I need to specify "Object Type" from the menu, or use drag and drop and it creates the reference on the fly, but since "Add Script" is dynamic, I don't know beforehand which script is exactly added at runtime. Any ideas? Alternatively, is there a way to define Object Type by string?

Edit: yet another possibility, could a few lines be added to "Add Script" so that it allows the object to be stored for further use?

Thanks in advance!
« Last Edit: July 24, 2017, 01:11:25 PM by Thore »

Deek

  • Full Member
  • ***
  • Posts: 130
    • View Profile
Re: Get Property & Add Script -or- how to access script based on string
« Reply #1 on: July 24, 2017, 02:26:51 PM »
Response to the 'Edit': Yes, indeed you can add a few lines to store the created script for further use.
I tested it on my AddScript.cs, which you can download from the attachment and copy the code over to yours or use it as a reference.

There's still the general PlayMaker problem that you have to create an object-variable with the exact same object type as the script you create if you want the object to be local, but you can surpass that restriction by making any object global and using that one in "Store Result" (that works for whatever reason and applies the script's object type to the global object).

Thore

  • Sr. Member
  • ****
  • Posts: 341
    • View Profile
Re: Get Property & Add Script -or- how to access script based on string
« Reply #2 on: July 25, 2017, 03:09:58 AM »
Thanks a lot! I played around with this one, though I could not solve my issue of referencing the script. Unfortunately, I cannot pinpoint exactly what doesn't work. The reference to an attached script seems to be very finicky.

For example, I have a number of data-holding scripts, which are identical in their structure. For the sake of illustration, "green.cs" holds "string color = green" and "red.cs" holds "string color = red" etc. I want to read out the color name from such scripts. Of course they have in reality many more variables. So, I go ahead, I can make "purple.cs" and so on. As long as I have the name, I can Add Script and it's right there. But alas, that's where the trouble starts.

I then made an object variable "ColorScripts" and set it to one (say "Color.Generic", in name space Color) of these color scripts I mention above, and can then nicely access the properties in the action, say get the color string. But when I write the script from the updated Add Script you provided, say, "Color.Red" something is still missing. In debug view, Object Type shows "Color.Red" properly, but Object Type remains "Color.Generic".

ArgumentException: Field baseLevel defined on type Color.Generic is not a field on the target object which is of type Color.Red.
Parameter name: obj


Thanks again, I try to look for an entirely different solution now.
« Last Edit: July 25, 2017, 03:32:46 AM by Thore »

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 14684
  • Official Playmaker Support
    • View Profile
Re: Get Property & Add Script -or- how to access script based on string
« Reply #3 on: July 25, 2017, 03:32:40 AM »
Hi,

 If you can make a repro package with the scripts, the fsm and the logic that shows your reference getting lost, I'll have a look and come up with a solution.

 One way I deal with this kind of case is to make my own variable system that only leave in memory, and then I have a couple of actions dedicated in getting the various properties from them class that I can't put into Fsm variables.

the other way is to create a proxy class that can be saved in an FsmObject which then exposes via composition your actual class. BUT BUT BUT, FsmObject must be of type UnityObject which means assets and are subjects to garbage collections and can create huge memory leak if you are not taking care of them properly.

 Bye,

 Jean

Thore

  • Sr. Member
  • ****
  • Posts: 341
    • View Profile
Re: Get Property & Add Script -or- how to access script based on string
« Reply #4 on: July 25, 2017, 04:50:57 AM »
Thanks! I boiled it down to the essentials, and added the package.

You find in the scene a Creator object with an FSM. It has one script attached, called BlobList.cs which tells it the names of the scripts it should look out for. It will then create a new object, called "Blob" and attach the script to it, as specified in the list. The script is later supposed to specify properties of the Blob object it was attached to.

For the sake of illustration, it does this twice. One time with the first entry (Red) and one time with the second entry (Green). When you run the thing, you should see two blobs created in the hierarchy, with the proper scripts, one with Red, one with Green.

I know the script name, I know the script is attached, and I know that it has the proper variables, but what's missing is to reference the script also dynamically to get properties from it. In other words, how can Blob (Red) and Blob (Green), each learn the variable "myColor" as specified in the script attached to them?

The Blob prefab has two variable entries. myScript and Blob Color. The End goal is to read the string myColor from the dynamically attached script, and write this variable into "Blob Color" string as a Playmaker variable. This would normally be done with Get Property, but this only works when the script is known and already attached.

The scripts have a namespace to find them easier in the list, hence their names are things like "Colours.Red". The Blob prefab has a myScript object variable, which I configured to "Colours.Generic", which is a script of the exact same nature as the actual colours, just as a placeholder. I thought it might be possible to configure everything with this, and then somehow override Colours.Generic with Colours.<AddScript Name>.

I know it's a weird setup. The reason is to have the Blobs definable via scripts, and to be able to add them.

Thanks again :)
« Last Edit: July 25, 2017, 05:02:06 AM by Thore »

Thore

  • Sr. Member
  • ****
  • Posts: 341
    • View Profile
Re: Get Property & Add Script -or- how to access script based on string
« Reply #5 on: July 25, 2017, 05:57:59 AM »
Maybe taking a step back solves the issue:

You know Dungeons & Dragons and the likes. You have a character sheet, which is essentially a bunch of variables. And then you have characters that use copies of that sheet, but with values filled in.

Let's suppose you want something like that: You want to define the character via a text file (script etc)  and hand it over to Playmaker. By defining the character, i.e. name = Alice; Health = 100; you are also in a sense determine how the sheet looks like. So in a simple way, all that is needed are character sheets. But of course, playmaker doesn't know in advance how the characters are named (or how the script is called) leading to the problem above.

In my current method, they are each their own script class, say Alice, Bob, Charly etc. It would be better to somehow have one class, e.g. "Characters", which is akin to a character sheet, and then somehow get the specific values for Alice, Bob and Charly from a text file.

By using one class, things are easy for playmaker, since then you can simply reference that class script and be done with it. But then I don't know how to organize the data for Alice, Bob, and Charly, and have them loaded. What is the best way to do this?






jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 14684
  • Official Playmaker Support
    • View Profile
Re: Get Property & Add Script -or- how to access script based on string
« Reply #6 on: July 25, 2017, 08:31:08 AM »
Hi,

 typically for this, I would go all the way with Xml, and not classes for many reasons.

- no issues with reflections, it's pur data
- it's flexible, data can grow and evolve without compromising existing apps or logic
- it's plain english, and understandable by non programmers
- it's cross platform, so you can store this data anywhere and edit, write read it anywhere ( for debugging, for website companion of your game)
- PlayMaker had DataMaker ( on the ecosystem) which provide extensive support for xml editing, and reading.

So I would simply go this way.

 now, if you still want to use classes,

- you will need to create custom actions to work with them, no real way around this, but since you are already scripting, doing the dedicated actions is trivial in this case.
- You will need a behavior ( let's call it CharacterSheetManager), which will be the middleman between PlayMaker, Unity world and interactivity and your data, the classes will be known by CharacterSheetManager and exposes in a friendly manner using a public API, which you can access from PlayMaker via Custom actions.

I'll take a look at your package within the next few days, but chances are I will strongly recommend using xml unless you have some good use case to make the use of classes better.

 Bye,

 Jean

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 4613
    • View Profile
    • jinxtergames
Re: Get Property & Add Script -or- how to access script based on string
« Reply #7 on: July 25, 2017, 08:57:26 AM »
Hi,
You can find a DataMaker tutorial here

And i think there is another one on the User Tutorial Wiki page

Thore

  • Sr. Member
  • ****
  • Posts: 341
    • View Profile
Re: Get Property & Add Script -or- how to access script based on string
« Reply #8 on: July 25, 2017, 10:19:51 AM »
Superb!

The current thing is a prototype only, hence I wanted others to add scripts/specification this way to play around a bit.

DataMaker looks promising, and maybe I can use it this time already. I'll definitely familiarize myself with this in the longer run, as this problem will likely come up again. Thank you.

EDIT2: I learned a great deal about reading data from all kinds of text definition files. However, none of this works when the files are external or in StreamingAssets folder. This is a hard barrier that requires more solid programming language (be warned, it always seems to work and the solution always seems to be just around the corner).
« Last Edit: August 01, 2017, 05:23:35 AM by Thore »

nFighter

  • Beta Group
  • Full Member
  • *
  • Posts: 139
    • View Profile
    • multiplayer adult fighting
Re: Get Property & Add Script -or- how to access script based on string
« Reply #9 on: October 08, 2017, 08:40:55 PM »
Hey, guys! I'm solving almost the same task but I lost you somewhere in the middle of the discussion  :'(

Let me summarize once again in a simple words:
1) I add a script "DynamicBone" to the object;
2) I record reference to the script in the variable "ScriptReference"
3)...now I need to set "m_Root" property of a script (or any other property), but I don't understand how exactly. Dropdowns of the "set property" action don't allow me to use any custom field.     



(I put the script manually to the object, for the reference)
indie developer of multiplayer adult fighting
http://nakedfighter3d.com

Deek

  • Full Member
  • ***
  • Posts: 130
    • View Profile
Re: Get Property & Add Script -or- how to access script based on string
« Reply #10 on: October 09, 2017, 05:53:52 AM »
@pigglet
You need to specify the type of Object inside your "ScriptReference" variable. In the 'Variables"-Tab click on "ScriptReference" and in the upshowing panel at the bottom select the 'Object Type' of the script you want to use (in this case "Dynamic Bone"); but you need to search for it, because it lists all available classes and namespaces. If you don't find it immediately you can look into the DynamicBone.cs script and near the top it might say something like "namespace db.scripts", then it would be under 'db>scripts>Dynamic Bone' (you can see that namespaces are like a folder structure).

Get Property and Set Property can only offer the properties of the given Object Type, and you haven't specified one yet (the default one is "UnityEngine.Object", which only has 'hideFlags' and 'name').

I admit it's a bit weird to set a variable type to Object and then also having to specify the Object Type, especially since it's not that obvious to do so and both field are called 'Object' by default, but you get used to it.

nFighter

  • Beta Group
  • Full Member
  • *
  • Posts: 139
    • View Profile
    • multiplayer adult fighting
Re: Get Property & Add Script -or- how to access script based on string
« Reply #11 on: October 09, 2017, 12:29:28 PM »
Thanks a lot! Now it works perfectly for me!
indie developer of multiplayer adult fighting
http://nakedfighter3d.com