Unity3D define static js var available from c# - unity3d

I am trying to define a static var in UnityScript.
The problem is that my script does not reside within a class.
How can i create a global variable that can be accessed from a C# class and
a UnityScript script?

The first thing to do is place the scripts in the correct folders in your Project tab. The script you want to have access must be inside the Standard Assets or the Plugins folder. The other script has to be placed outside these folders. After this step, just call the GetComponent() method as any other Component. Here’s a JavaScript example:
//create a variable to access the C# script
private var csScript : CSharp1;
function Awake()
{
//Get the CSharp Script
csScript = this.GetComponent("CSharp1"); //Don't forget to place the 'CSharp1'
file inside the 'Standard Assets' folder
}
//... code here
Now, here’s a C# example:
using UnityEngine;
using System.Collections;
public class CSharp2 : MonoBehaviour
{
//create a variable to access the JavaScript script
private JS1 jsScript;
void Awake()
{
//Get the JavaScript component
jsScript = this.GetComponent<JS1>(); //Don't forget to place the 'JS1' file inside the 'Standard Assets' folder
}
//...
}
And this is how it’s done. There’s no way to have access to C# and JavaScript simultaneously, as one of the scripts must be at Standard Assets or Plugins folder. Scripts placed inside one of these folders are compiled first, meaning these scripts can’t access the ones outside it, as they are not compiled yet (more information here).
There is a Project With Example here

Related

How to bake or compute my script data before play

So, I am working on a unity project that involves a lot of math. It takes about 1-2 seconds for the math to finish on start.
Is there any way to "bake" or "compute" this data before the game starts. I saw something similar done in this script from this project. My project has nothing to do with this script, it is just an example.
I would prefer not to share my code. I need to compute the variables from a method called Initialize()
I fixed this by using [SerializeField, HideInInspector] before the variables I wanted to bake.
Then I would create a new class (can be in the same script). You have to using UnityEditor then your class should be something like
[CustomEditor(typeof(classToBake))]
public class BakeGUI : Editor
{
}
Call function override public void OnInspectorGUI() then call functions of the type EditorGUILayout Then you have to create a variable of the type of script.
using UnityEditor;
[CustomEditor(typeof(classToBake))]
public class BakeGUI: Editor
{
override public void OnInspectorGUI()
{
classToBake bake = (classToBake)target;
if (GUILayout.Button("Compile Data"))
{
bake.Compile();
}
if (GUILayout.Button("Delete Data"))
{
bake.ResetData();
}
DrawDefaultInspector();
}
}
Finally, how to use this.
change classtoBake to the script with the data you want to bake
In the if statements, you can run methods when they click the buttons.
The most important thing
After you have this working, to save your data, YOU MUST have the variables you are going to change have the attributes [SerializeField, HideInInspector]

Creating an array/list of scripts for a Scriptable Object

So, I have an ItemObject which is a ScriptedObject
In an ItemObject I want to create an array/list that stores the scripts in it
The scripts that will be stored in this array/list will be used to extend the functionality of the GameObject (Imagine as unique skills for player, not attributes)
To do this, I'm going to add the script as a component with Player.AddComponent(SCRIPT.GetType())
So, it is assumed that after I create an item asset in the project directory, I can select the number of script skills and add them through the inspector
Also, as a sad alternative, I was considering using GameObject, which would store scripts as components. And that, to me, is terribly unhandy, given that there could be hundreds of the scripts. And unfortunately, I'm still not experienced enough, so it's the best I've come up with so far.
I solved my problem in the following way:
By adding the script as an Object and displaying its type in the console, I found out that it is a MonoScript
So just by adding using UnityEditor I was able to create a list consisting of MonoScript
using UnityEditor;
class Script : MonoBehaviour
{
List<MonoScript> scripts
}
And then, using [GameObject].AddComponent([MonoScript].GetClass()) I was able to add this script as a component to the GameObject
class AddScriptAsComponent : MonoBehaviour
{
GameObject object;
MonoScript script;
void Add()
{
object.AddComponent(script.GetClass())
}
}
You could do something like
using UnityEngine;
public class ItemObject : ScriptableObject{
[SerializeField] List<MonoBehaviour> scripts;
}
Although, if I'm understanding the objective correctly, maybe it would be a good idea to have a look at the concept of prefabs instead.

How do I make an array with all Scriptable Objects from a folder in Unity?

So this is the Scriptable Object:
[CreateAssetMenu(fileName = "New Char", menuName = "Char")]
public class ScriptableChar : ScriptableObject
{
public string charName;
public Sprite charSprite;
public Sprite charBorderSprite;
public CharClass charClass;
}
And I have tried this to get the array:
public Object[] allCharacters = Resources.LoadAll("Cards");
and this:
void GetAllCharactersArray()
{
ScriptableChar[] allCharacters = Resources.LoadAll<ScriptableChar>("Cards");
Debug.Log("Characters: "+allCharacters.Length);
}
I have also tried a few other things I have deleted because they haven't worked either.
Image of the Folder structure if that is needed or matters in any way.
I would be really happy if someone can help, I have been trying to solve this for many hours now.
Okay, so first things first: Resources only works for assets in a folder called "Resources". You can't load the assets from "Assets/Cards", because they are not located in a Resources folder and not indexed to be loaded by the helper class. See the docs for Resources.
Resources are bad practice. I don't know what you want to do, but I assume, you want to access the cards and other assets somewhere. A common way to do would be to create a ScriptableObject that references all of these assets in lists and then use a reference to an instance of this object anywhere you want to access the data.
If you want to auto-assign the references in the editor, you can do so using an Editor script that searches in the folders, picks up all the references and stores them in the instance of said ScriptableObject.

Can I #define a constant solutionwide within c# code without project settings?

I know this was aksed and answered a a couple of times e.g.
Solution-wide #define, Is There anyway to #define Constant on a Solution Basis? and How to define a constant globally in C# (like DEBUG).
But in my case I can not use any of the suggested methods:
I'm writing on different "modules" (or plugins if you want so) for UnityProjects (kind of a package providing a certain functionality). The idea is that a developer can load a certain "module" to use in his project by importing a UnityPackage with all scripts and resources in it.
But some of these modules themselves depend on other modules. So what I tried so far was having a class Constants in each module with seperated namespaces and preprocessor definitions.
Module A
#if !MODULE_A
#define MODULE_A // BUT I WOULD NEED THIS GLOBAL NOT ONLY HERE
#endif
namespace Module_A
{
public static class Constants
{
// some constants for this namespace here
}
}
Module B
#if !MODULE_B
#define MODULE_B // BUT I WOULD NEED THIS GLOBAL NOT ONLY HERE
#endif
#if !MODULE_A // WILL BE NOT DEFINED OFCOURSE SINCE #define IS NOT GLOBAL
#error Module A missing!
#else
namespace Module_B
{
public static class Constants
{
// some constants for this namespace here
}
// and other code that might require Module A
}
#endif
But ofcourse this cannot work like this since #defines are not global but only in the current file.
Problem
For this whole idea of modules and a simple "load your modules" I can not ask the user to first make changes to the project or solution settings how e.g. suggested by this answer but instead have to use only the (c#) resources that come imported with the UnityPackage (at least with my current know-how).
Is there any way to somehow set/define those constants for the entire Unity-Project by only importing the module's UnityPackage?
Edit:
I could find a solution for 1 definition in Unity using Assets/msc.rsp. But this still wouldn't work for multiple modules since they would have to write into the same file.
After a lot of searches I've finally been able to put together a surprisingly simple solution I'ld like to share with you:
InitializeOnLoad
Unity has an attribute [InitializeOnLoad]. It tells Unity to initialize according class as soon as
Unity is launched
After any re-compiling of scripts => also after importing a new unitypackage with scripts
static Constructor
In their Running Editor Code On Launch example, they show, how to combine this with a static constructor.
From static-constructors:
A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced.
While usually you still would have to create an instance of the class, the static constructor is "instanciated/executed" instantly when the class is initliazed, which we force using the [InitializeOnLoad] attribute.
Scripting Define Symbols
Further Unity actually has project wide defines in the PlayerSettings.
And the good part is: We also have access to them via scripting API:
PlayerSettings.GetScriptingDefineSymbolsForGroup
PlayerSettings.SetScriptingDefineSymbolsForGroup.
So what I did now is the following
Module A
This module has no dependencies but just defines a "global define" in the PlayerSettings. I placed this script somewhere e.g. in Assets/ModuleA/Editor (important is the last folder's name).
using System.Linq;
using UnityEditor;
namespace ModuleA
{
// Will be initialized on load or recompiling
[InitializeOnLoad]
public static class Startup
{
// static constructor is called as soon as class is initialized
static Startup()
{
#region Add Compiler Define
// Get the current defines
// returns a string like "DEFINE_1;DEFINE_2;DEFINE_3"
var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
// split into list just to check if my define is already there
var define = defines.Split(';').ToList();
if (!define.Contains("MODULE_A")
{
// if not there already add my define
defines += ";MODULE_A";
}
// and write back the new defines
PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, defines);
#endregion
}
}
}
Module B
This module depends on Module A. So itself defines a "global define" (so later Modules can check their dependecies on Module B) but additionally it checks first, if Module A is imported. If Module A is missing, it prints an error to the Debug Console.
(You could as well throw a compiler error using #error SOME TEXT, but for some reason this is not capable of printing out the URL correctly so I decided for the Debug.LogError)
I placed this script somewhere e.g. in Assets/ModuleB/Editor
#if MODULE_A
using System.Linq;
#endif
using UnityEditor;
#if !MODULE_A
using UnityEngine;
#endif
namespace ModuleB
{
// Will be initialized on load or recompiling
[InitializeOnLoad]
public static class Startup
{
// static constructor is called as soon as class is initialized
static Startup()
{
#if !MODULE_A
Debug.LogErrorFormat("! Missing Module Dependency !" +
"\nThe module {0} depends on the module {1}." +
"\n\nDownload it from {2} \n",
"MODULE_B",
"MODULE_A",
"https://Some.page.where./to.find.it/MyModules/ModuleA.unitypackage"
);
#else
// Add Compiler Define
var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
var define = defines.Split(';').ToList();
if (!define.Contains("MODULE_B"))
{
defines += ";MODULE_B";
}
PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, defines);
#endif
}
}
}
So later in other scripts of Module B I have two options (both do basically the same)
I can either check everywhere #if MODULE_A to check exactly the module this script relies on
or I can instead check #if MODULE_B to rather check with one line if all dependecies are fulfilled since otherwise I don't define MODULE_B.
On this way I can completely check all dependencies between certain modules which is awesome. The only two flaws I saw until now are:
We have to know how the define (e.g. MODULE_A) looks like for every module and if it is changed in the future it has to be changed in all depending modules as well
The "global define" isn't getting removed in case the module is deleted from the project
But well - which solution is perfect?
In general, the way I would solve this problem in C# is by defining a common set of interfaces that all your modules would contain. I think you can do this with Unity by placing the files from each module in the same location, thus allowing later installations to overwrite those same files (with, obviously, the same content). You would then put editor controls that expose properties to hold instances of those interfaces and then wire them up in the UI. You would test those properties for a value of null to determine which ones are missing.
Common.cs:
public interface IModuleA {}
public interface IModuleB {}
ModuleA.cs
public class ModuleA : IModuleA {}
ModuleB.cs
public class ModuleB : IModuleB
{
public IModuleA ModuleAInstance {get; set;}
private bool IsModuleAPresent()
{
return !ModuleAInstance == null;
}
}
The ideal way to solve it would be with a package manager and proper dependency injection, but doing that with Unity is not straightforward.

Can't assign ScriptableObject in inspector

I'm having trouble with assigning ScriptableObjects in inspector.
For example, I have this class:
using UnityEngine;
public class Buff : ScriptableObject {
public string buffName;
}
In one of the monobehavior-derived classes, I have a member like this:
public Buff testBuff;
In inspector I see the following, but I can't drag+drop script 'Buff' to this member
It works to drag+drop Buff as a new script, but I can't add it to 'Test Buff'.
What I tried instead of dragging+dropping is to simply create an instance of Buff like so:
public Buff testBuff = new Buff();
This worked:
However I believe drag+drop should work as well, plus the above gives warning:
Buff must be instantiated using the ScriptableObject.CreateInstance method instead of new Buff.
UnityEngine.ScriptableObject:.ctor()
Buff:.ctor()
...
I'm using Unity "5.0.2f1 Personal", which is the latest version.
You need to create an asset file that uses your Scriptable Object as it's type. This can only be done with an editor script. There is a generic one on the wiki.
Essentially you just create a menu item for each Scriptable Object type you have, use the menu item to create assets of those types, and then modify the assets with the values you want them to have. It's important to remember that SCOs are to be used as templates, if you modify a SCO either in the editor or with code those changes will instantly take effect on all GameObjects and Components that reference the SCO.
create asset with specific file extension inside custom inspector using EditorGUILayout.ObjectField; DefaultAsset; Open/Save dialog
detail video how do it
That's because you did not add[System.Serializable] at the Buff:ScriptableObject class, so all your "buff" is not serializable, and Unity Editor can't read c# directly, it can only read c# that are serialized.