#↕️┃editor-extensions
1 messages · Page 110 of 1
How can I get the center position of an active area of graphview, so I can get the center of it later on?
For nested fields/props, how can I calculate the correct position for them?
var initialPos = EditorGUI.PrefixLabel(position,label).x;
It only works for root fields
var initialPos = (EditorGUI.PrefixLabel(position, label)).x - 15 * EditorGUI.indentLevel;
It solves the initial position of nested fields but width is wrong!
.
Thank you, EditorUtility.SetDirty did the job. I didn't realise there was a pinned message with so much useful links, thank you.
How so?
Btw there is EditorGUI.IndentRect(..) for indenting the rects the proper amount. (Or maybe it is EditorGUIUtlity, I can't remember)
does anyone here happen to know how to use the currently experimental Graph View?
I created a system where for every variable in a node script with the attribute of [Port], a port will be created
it's currently really slow but the point is, it works
and I need to somehow link references using edges
There's a tutorial on graph view pinned to this channel that's a good starting point
yeah but I don't know how to adapt them to my method of creating the links
the edges
I will check it out nontheless
oh
I already watched that one tho
I use this higher-level library to create my own tools with GraphView. It's made by a Unity employee as a personal project.
https://github.com/alelievr/NodeGraphProcessor
oh wow I guess I'll use this one
it seems to be doing exactly what I want it to do, in the same method I made
thanks!
whats happing inspector not sees my project and unity can open project only if make new
and sends error of method axess team license
I cant edit my project
please help me
i find questions but is nothing
hey, I have an EditorWindow with a ReorderableList
problem: as my items are Types (and therefore not serializable) I have to use the Type ctor and dont have access to ReorderableList.serializedProperty ```cs
m_list = new ReorderableList(m_managers, typeof(Type), true, true, false, false); //with m_managers = List<Type>
How can I reorder my m_managers after moving elements in list please?
It will do that already, will it not?
nope, unfortunately
it keeps reordering itself when i click the "add" or "remove" buttons
how's that implemented?
In the Unity version I'm testing in (2022.1) reorderable list modifies the list you pass in
If you reorder the list in the inspector, the original is modified. No copy was made.
with non-serializable items?
Yes
i see
thx anyway :/
would you mind if I take a look at your code? (you cans send me a dm if you agree)
maybe i'll find what i did wrong xD
public class Managers : EditorWindow
{
[MenuItem("Window/Managers")]
private static void ShowWindow()
{
var window = GetWindow<Managers>();
window.titleContent = new GUIContent("Managers");
window.Show();
}
private readonly List<string> m_managers = new();
private ReorderableList _mList;
private void OnEnable()
{
_mList = new ReorderableList(m_managers, typeof(string), true, true, true, true)
{
drawElementCallback = (rect, index, _, _) =>
m_managers[index] = EditorGUI.TextField(rect, index.ToString(), m_managers[index])
};
}
private void OnGUI()
{
_mList.DoLayoutList();
if (GUILayout.Button("Test"))
{
foreach (string mManager in m_managers)
{
Debug.Log(mManager);
}
}
}
}```
Yeah, ya did something wrong I think 😛 It has always modified the list that you pass.
string is serializable
it's not being serialized, and it wouldn't matter if it was
ahhh i just wanna throw my computer by the window lmao
What's the Add implementation?
you mean when I fill the list?
what's hidden here
ahh
if (GUI.Button(new Rect(_rect.x + _rect.width / 2, _rect.y, _rect.width / 4, _rect.height), "Add",
EditorStyles.miniButtonLeft))
{
//switch current manager style: dedicated object or common object, then process it
switch (attr.m_style)
{
case ManagerStyle.COMMON:
ProcessAddCommon(ref managersObject, manager);
break;
case ManagerStyle.DEDICATED:
ProcessAddDedicated(manager, attr);
break;
default:
throw new Exception("unsupported");
break;
}
//mark scene as dirty
EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
it's to add it in scene
how does the window.m_managers list get modified here?
it does not
so why would the add button change the order of the list
i fill it at beginning and never edit it manually
it's just that when i click the button it resets list order
That's bizarre. Is the window being reloaded?
nope
that's just.. weird
omg wait
hahaha found it
i forgot i called the init function in my 'OnHierarchyChange' i'm so dumb
Now, it is OK. I set the indent level to zero and then revert back at the end.
My problem
Field labels do not have indent. (ip2 and ip3)
EditorGUI.LabelField has not been used. I do not know how they are rendered!
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var height = position.height;
var posY = position.y;
var offset = height / 2f;
//EditorGUI.LabelField(position, property.displayName);
EditorGUI.BeginChangeCheck();
var ipValue = (IPAddressV4)property.GetValue();
var indentLevel = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
// render int fields
EditorGUI.indentLevel = indentLevel;
Can anyone explain me how I can override the function of that add element button on a normal inspector list. I already made a custom editor for that script but now I don't know how to proceed...
Hey, I'd like to query gameobjects in (unloaded!) unity scenes. I'd like to get the positions of all the gameobjects that have a collider component.
What I can do here is to parse the unity yaml file with YamlDotNet and resolve the transform hierarchy manually. I'm wondering if there is a better solution for this?
to have all the physics colliders loaded in my backend (I started with this manual loading because like this I could support hot reloading for local development)
Beyond physics objects, I'd like to also be able to define things using the unity world editor like placing monster spawners, defining player spawn points, points of interests, zone bounding volumes, etc.
^This is a no-brainer after I can query the boxcolliders, just writing this to give better context
Btw @crude relic I successfully parsed the scene file but hit the roadblock with prefabs, it points to a guid and I can only resolve those with access to assetdatabase, so if I see it correctly, I'm unable to parse the scene file completely outside of Unity itself.
EditorGUIUtility.editingTextField does not work correctly!
I would like to have a normal style when a text field is editing but when I click on a button and not focused, it should have another style.
After switching between windows and again click on a button, it would be OK
Also, there is a null error, it is destroyed (texture) unity editor after playing and close
Is it a standard way to solve it?
public class BackgroundStyle
{
private static readonly GUIStyle Style = new GUIStyle();
private static Texture2D _texture = new Texture2D(1, 1);
public static GUIStyle Get(Color color)
{
if (_texture == null) // here
{
_texture = new Texture2D(1, 1);
}
_texture.SetPixel(0, 0, color);
_texture.Apply();
Style.normal.background = _texture;
return Style;
}
}
It didn't destroy the texture, simply lost the reference to it since it is only in memory. And when you enter/exit play mode or recompile scripts, the domain is reloaded and all C# static fields and events and such are reset to their default value.
Is it possible to use a fade group in a property drawer? I'm making a property drawer for a class that contains a list and I want the foldout to animate open to reveal the list instead of opening immediately. it seems this is not possible since property drawers don't use the layout system tho. can anyone confirm this?
if(Event.current.commandName == "ObjectSelectorUpdated") Object reference not set to an instance of an object
Yeah, guess the event doesn't propagate to the update method
so no can do?
Correct-ish
It gets uglier from here 😛
What is it that you are wanting to do? Perhaps there is a better solution
(Just fyi, memes and such are not allowed in the server because they take up so much space and can clog up or derail conversations)
oh, whoops, sorry
I wanted to create a MenuItem that would (essentially) do something similar to a UI Image (albeit with some differences that aren't necessary to the context). When you click it, a "Select Sprite" window would pop up (similar to what happens when you change the image on a UI Image). Once you select one, it would automatically make a UI Image with the selected sprite already assigned to the object along with it correct size.
Oooh, hmmm
I already know how to create the object and give it the same properties, what I dont know how to do is to display that "Select Sprite" window and assign it to the new image component.
Righto, so taking a look at the source code, it looks like you can do it using some reflection if you want.
You would get the ObjectSelector class and then get this Show(..) method and use that to open it https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/ObjectSelector.cs#L417
As you can see @nocturne geyser it takes a Action<Object> onObjectSelectorClassed delegate as a param.
So it should be pretty easy to setup! No need for funky update loops or anything.
how would I use that in code? Is it a ObjectPicker.Show() along with some sort of using UnityCsReference; kind of thing?
Have you used reflection before?
No
Right-o so I would read up on it a bit. It is really handy, especially when doing editor scripting. It allows you to 'dynamically' get members (fields, methods, properties etc.) of a class, and also get private or internal members.
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection
you sure there isn't a public api for that? I swear I've used the object selector before w/out having to do reflection shenans
🤔
mb I'm just making stuff up
There is only the EditorGUIUtility.ShowObjectSelector(..)
ahhh that must be what I'm thinking of
Managed to center newly spawned nodes into graphview, I bet there is an easy way to do this rather than rolling your own math
schedule.Execute(() =>
{
var graphView = vg._vviews.viewTransform.position;
var graphViewScale = vg._vviews.scale;
var editorWindow = vg.position;
vnode.SetPosition(new Rect((-graphView.x + (editorWindow.width/2)) / graphViewScale, (-graphView.y + (editorWindow.height/2)) / graphViewScale, editorWindow.width, editorWindow.height));
vnode.RefreshPorts();
vnode.RefreshExpandedState();
});
i'm open for suggestion
pretty sure xMin yMax do the same thing.. ugh
I'm trying to create my own click & drag functionality in my EditorWindow script, but it seems I can't get the event for that, the built in "box select" behaviour overrides what I'm doing, and I don't get any more events until the mouse button is released and the built in blue selection box disappears.
This page seems to describe exactly my problem, and an apparent solution, but not quite what I want - he's clicking on some object he created. But I need to start clicking and dragging from any collision the user clicks on. Kind of like the way you click to drag select units in a 3D RTS. Wherever you click on the terrain, a box will drag out horizontally from that location.
https://stackoverflow.com/questions/63040319/unity-editor-capture-hold-mouse-down-and-move-event
I'm currently having an awful time trying to fight the scene camera. I have a level editor that runs in scene view. A part of that is scrolling to change the placed tile. As far as I can tell, there's no way to stop unity zooming on scrolling, so instead I have to set it back on Camera.onPreRender which will jitter half the time. I need to subscribe to that event though, which doesn't survive any sort of reload, so I need to run IntializeOnLoadMethod to reset it, but that only works for static methods, so I need a singleton to actually set it. I don't even know what's going on memory leak wise with the very dodgy subscribing and unsubscribing, but I don't imagine it's good.
Any advice? Some way to stop the zoom? A better place to set the camera size to avoid it jittering? Some way to make the event subscription not awful?
Also forgot an additional pain. You can't get the sceneview at InitializeOnLoadMethod. I don't even know how I had this working earlier. This is pain.
anybody knows how to show default inspector on top of uielements?
Found the exact example for this https://github.com/Unity-Technologies/UIElementsExamples/blob/master/Assets/Examples/Editor/Bindings/InspectorComparerWindow.cs
@craggy latch if you subscribe to https://docs.unity3d.com/ScriptReference/SceneView-beforeSceneGui.html you can override keyboard and mouse events that would otherwise be consumed by the sceneview
make sure to call Event.current.Use()
I got it to behave the way I want during the drag, but the built in blue drag-box still appears over the top of it, and then I don't seem to get the MouseUp event. Probably need to fiddle with it some more...
@old ravine same applies to you lol
subscribe to beforeSceneGui
it allows to override default scene behavior
Oh thank god, I couldn't find anything on this. Thank you.
np
Oh, hahah.... ok I will do that in the morning, thank you 🙂
And I after I'm back at my PC. Let's hope this goes smoothely.
you also need to manage GUIUtility.hotControl
if you don't register/set your own control id it won't override the default functionality
@crude relic Also It's doing a weird thing where the DrawLine that I'm using smears across the screen and only refreshes the 3D view correctly at some kind of intervals that I can't determine, seems when I stop moving the mouse. Maybe your solution will help with that too.
whenever you're doing mousedrag stuff in the scene, make sure to call SceneView.RepaintAllViews or whatever it is
so it repaints consistently
never run into smearing before tho
are you using Debug.DrawLine
I'd absolutely have made that mistake. Would you mind if I @ you if I have any troubles with this when I get back? I haven't done too much with editors before.
you should be using Handles.DrawLine
sure
cant guarantee I'll be online tho 😄
👍
yes, Debug.DrawLine is runtime-only
for editor you either want gizmos or handles
handles in this case
Lifesaver man, it works perfectly 🙂
it will behoove you to dig into the Handles and HandleUtility classes
they are necessary for sceneview editors
Yes I'm compelled to do that now
I have an editor extension that opens a simple EditorWindow when I press a button. Is it possible to persist that EditorWindows location in unity's layout after I exit and re-open unity? Pressing 'save layout' doesn't seem to save the location of my extension's window.
Usually the first thing I do is dock the window
It opens as a popup, but I want it to just be another panel
it is possible to save the position of the panel if it's been docked
Oh, when I load the editor layout, I get this error: The editor layout could not be fully loaded, this can happen when the layout contains EditorWindows not available in this project
yah makes sense
it can't find your window
make sure it's in a file that matches the class name
and isn't an inner class
It is not in a file matching the class name 🙂
that would explain it then
👍
Hi everyone! I'd like to create a prefab that when dragged into the hierarchy, the user will be prompted to input an integer. Then that number of prefabs will be created as children of an empty game object. Is this possible with code? If prompts aren't possible, public variables in the inspector should be fine as well!
How would you go about subscribing to this? Right now I've got some akward singleton stuff going on because there is no 'onenter/exiteditmode' I can find.
Idk what you are doing, but would just subbing in a InitializeOnLoad static constructor work? And if you need playmode state change there is this
https://docs.unity3d.com/ScriptReference/EditorApplication-playModeStateChanged.html
That's what I'm currently doing, though I'm not sure that's a good idea since that runs everytime there's a reload and I'm not unsubscribing properly. It also requires me to make a singleton since that needs a static method.
No need to unsub since it is cleared on domain reload. And no need for a singleton either (not sure what you are doing currently so not sure what to suggest instead).
How would I statically subscribe it? Unless I make the whole thing static.
[InitializeOnLoad]
public class Example
{
static Example()
{
// Sub
}
}
or
public class Example
{
[InitializeOnLoadMethod]
private static RunExample()
{
// Sub
}
}
Yes. You would need the instance of Example to sub to the event.
There no good way to prompt the user for values before continuing
What are you trying to accomplish?
Anyone know if there is there a good way to serialize the value of a SerializedProperty?
Uh
Ok, but I'm suspicious of making things static to solve problems like that.
It's perfectly fine in this case
It's a problem of your own making
Initialize on load is static
Event handler is static
Event delegate is also static
Everyone wins
I'm assuming you mean like, write the value to disk?
Bc the obvious answer is that it is already serialized
I don't think there's a way where you're not having a giant switch case
You can also look into constructing a custom tool
That may appeal to your non-static sensibilities a bit more
And then you have a strict lifecycle since it's tied to having the tool enabled
Noted. Thanks.
@crude relic I've got this running and it works great.
private static void BeforeSceneGUI(SceneView sceneView) {
Event guiEvent = Event.current;
if (guiEvent.type == EventType.ScrollWheel) {
if (!guiEvent.shift)
guiEvent.Use();
}
}
Small problem though, I need to use the scroll event for another script. You mentioned the hotcontrol thing for that, but I don't understand it. Could you give me some pointers? I could also just tell the other script to do it's thing from here, but want to learn what the hotcontrol thing is.
Haha yeah I mean write it to some sort of serialized format (bytes, json string, etc.).
Part of the problem is that I need it to be really generic, so it can handle any property value. The reason being is I basically need to be able to store the value of any given property and then restore the property to that value at another point in time.
I'd just like to make a prefab which help other developers easily spawn a specified number of object by just specifying an integer.
so im making a tool to make duplicating a lil bit easier. the duplicating of the object with its position, rotation and scale are working fine but im having issue with the preview mesh it is displaying. as seen in the video, the preview mesh itself has a different rotation than the actual mesh itself and im scratching my head for a fix, any idea on how to fix the preview mesh rotation issue?
the code for the preview mesh itself. i suspect the issue is with the Matrix, not sure...
if (inputInstances > 0 && Selection.gameObjects.Length == 1)
{
GameObject go = Selection.gameObjects[0];
MeshFilter[] meshFilter;
// Get the existing MeshFilter component from the selected gameObject
// If it doesn't exist, then get the MeshFilter component from the child gameObject(s) instead
if (go.GetComponent<MeshFilter>() != null)
{
meshFilter = go.GetComponents<MeshFilter>();
}
else
{
meshFilter = go.GetComponentsInChildren<MeshFilter>();
}
if (meshFilter != null)
{
foreach (MeshFilter filter in meshFilter)
{
GameObject currGO = filter.gameObject;
Mesh currMesh = filter.sharedMesh;
for (int i = 1; i <= inputInstances; i++)
{
Vector3 finalPosition = CalculatePosition(currGO.transform.position.x, currGO.transform.position.y, currGO.transform.position.z, i);
Quaternion finalRotation = currGO.transform.rotation * Quaternion.Euler(inputRotation.x * i, inputRotation.y * i, inputRotation.z * i);
float scaleX = inputScale.x;
float scaleY = inputScale.y;
float scaleZ = inputScale.z;
Vector3 finalScale = new Vector3(scaleX, scaleY, scaleZ);
// Create a translation, rotation and scaling matrix
Matrix4x4 matrix = Matrix4x4.TRS(finalPosition, finalRotation, finalScale);
_previewMaterial.SetPass(0);
Graphics.DrawMeshNow(currMesh, matrix);
}
}
}
}
does anyone know why AssetDatabase.Refresh doesnt refresh resources folder? I can only get it to refresh by recompiling my code
After using var inputRect = EditorGUI.PrefixLabel(position, label);,
I see text value which is in the text field on the label overlapped!!!
.
Are you using inputRect for the second label?
It should. What are you wanting and what are you seeing/not seeing?
The traditional way to do something like that would be to create a custom editor window
yes
var inputRect = EditorGUI.PrefixLabel(position, label);
inputRect.x -= EditorGUI.indentLevel*15;
inputRect.y += inputRect.height;
inputRect.width -= 60;
_input = EditorGUI.TextField(inputRect, _input, _style);
the first one is pattern and the second one is input rect
I have an icon generator that makes pngs of items in my game, it runs in the editor, it generates and imports the icons just fine (saves them to resource folder) I call asset database refresh after that, but it never finds them until I force I manual recompilation of all scripts (by changing random code around or adding a comment etc)
Ouch, might be out of my expertise. Thank you though!
This is inputRect.x -= 15 * 15;
After that code runs I want to assign the icons to the items, but resources.load never finds them
so I have to do a manual refresh for it to work
Sorry I just reread it, I thought it was indent width, my bad
But you see the files in the project browser?
The second text field should not have any label
Yes
I have an import preset and everything, they load in just fine, only thing that fixes it is me manually compiling the assemblies
Assetsatabase.refresh won't import them, you need to import them
I can't remember the overload
Is it in assetdatabas
?
Something like assetdatabas importassets
AssetDatabase.ImportAsset(..)
Yah
They get imported just fine, I can see them in the unity browser, just resources folder can't see them
I'll try this in a bit
You should turn off automatic imports before and turn them on after
And then use the bulk import overload
Will make it much faster
Off automatic refresh actually I think it is
Make sure to use a "try catch finally" to enable it again!
(@crude relic you have too much faith that people understand what they are doing!)
I like to give the broadest solution and then work inward as necessary
Saves me effort and lets people draw their own conclusions. Better for learning! 😁
Until stuff breaks and they come here asking for help 😛
Yah that's fine
I like to think I know what I'm doing 🥲
I didn't mean that as a slight against you. I have no idea what you do or don't know. So I try not to give people stuff that is too complicated if I can help it until I do know.
Basically the opposite strategy of me 😂
LOL
Yeah I know, don't worry about it! Just having some fun haha
I'm the same way when I help people as well
Is there a way to override a prefab property from script?
Just change the instance?
I am trying to understand exactly how the prefab override system works. And I want to see if it is possible to override a generic property without overriding one of its fields.
So override _myClass but without overriding _myClass._fooFloat
I don't understand what that even means, _myClass is not what it serialized if it contains children
so you cannot override it at all
do you mean overriding what type _myClass is
Is _myClass being serialized with SerializeReference or something?
Well that is what I am trying to figure out, because it has an 'override state' myClassProperty.prefabOverride will be true if one of the fields in _myClass is overridden.
// In Mono
[SerializeField] private TestClass _myClass;
// In its own file.
[System.Serializable]
public class TestClass
{
[SerializeField] private float _fooFloat;
}
Again, there is no 'end goal'. I am just trying to understand exactly how the system works so I can mirror it in my ScriptableObject Variants
I think I have figured it out, basically it just keeps track of which if any of its properties are overridden. And if any are, then it is too.
I imagine that's the case, because _myClass has no member in the serialization hierarchy
it isn't present in the YAML at all
you cannot override its value in any sense, only the values of the serialized properties that are the lowest children
SO variant is something that makes a lot of sense
surprised (not really) they haven't done that yet
That makes yeah
@gloomy chasm @crude relic sorry for the incredible delay, but using assetdatabase.importasset doesnt work, any ideas why?
yeah and alot of it isnt well explained in the docs unfortunately
cant really share the project, it's for my job :/
I wasn't suggesting that you should share it lol
Good a time as any to get fired 🤷
What's the setup with the Resources folder?
are you certain you're not just screwing up the call to Load
(like, does it work if you manually make the assets)
editor script spawns prefab, positions it, takes icon screenshot, saves it to resources folder, i call assetdatabase.importasset, it cant find at all, but if i force a recompilation of the project, it can find it, so something is going wrong with the resource folder refresh
If that's all good, try a AssetDatabase.Refresh perhaps?
thats what i was doing initially
it all works great if i manually compile the project (which i assume reloads resources)
but i cant get it to be automated
If you're running the load directly after creating the icon, are you using ImportAssetOptions.ForceSynchronousImport?
^
@wise yoke if you're making a lot, use AssetDatabase.StartAssetEditing to queue up the calls also
and StopAssetEditing of course
i will, but what does that do?
Well I think the answer is just to have a breakdown
queues up imports so it can batch them
makes importing faster
when you're doing lots of it at once
If you're making a load of assets a Start and Stop AssetEditing call will make it so there's one loading bar instead of a flickering mess of loading 😄
and it will be significantly faster
on a tangential topic I'm designing an asset that may generate lots of textures, and I'm contemplating generating the meta files myself so I can avoid the initial import step 🤔
I imagine the thing that takes time is messing with the Library, not the meta files
but I could be wrong
you're correct, but the messing with the library is what I'm trying to avoid
if you write a png file to disk then it needs to import that
if you then want to immediately change the import settings via code you need to reimport it
if I just set up the meta file with the import settings I want then no reimport necessary
If you StartAssetEditing it won't reimport until you're done modifying
yah but I need to get the importer to change and serialize the import settings
Ah I see
the whole texture gen workflow is garbage lol
making the meta file by hand just sounds super janky though
so I'm hesitant
sounds like something easy to break
I still am unsure whether having the meta file would skip you importing the asset before loading the importer
I would use a Preset over a meta file, but I'm unsure whether that helps the problem either
if it were possible to write a png to disk and apply a preset to it on first import then I'd be all over that
presets as in?
ye
it doesn't.
here -- the chain is like this:
write file -> import -> get importer, make changes -> re-import
is this why my thing doesnt work? i am using a preset for the icons
if I write the meta file by hand, it becomes this:
write file & meta -> import
Ah right, that makes sense, you don't need the importer if it's fine to begin with
I have no idea if my issue applies to your issue lol
exactly
but meta file is prone to breaking with version changes
so potentially lots of upkeep
maybe unity's serializer is robust to missing properties, so I can just write what I care about and let it fill out the rest lazily on some future re-import
I'd only need to do the manual part once, if the file already exists I'd just grab the importer
@wise yoke can you post the relevant snippet
tired of speculating w/out code
yeah sorry, cleaning it up so its easier to understand, 1 sec
no worries
this should be all thats relevant
i do the try catch finally thing around this method
The leading forward slash seems odd too
/Resources//UI/Icons/...
it doesnt matter, windows changes it to the right way around
afaik
You don't even need to do Application.dataPath
ImportAsset still needs the extension
It has it
The mixing and matching of string interpolation and concatenation is killing me 😄
i like to live life on the wild side
Is it possible that the AssetDatabase hasn't had time to update yet?
So Resources can't find it because it isn't there yet?
Also, you don't need to use Resources Load
just load it via AssetDatabase
AssetDatabase.LoadAssetAtPath
Yeah, that's what I would do. Already in an editor context
Hold up, what if it can't load it because you are trying to load it as a sprite and it isn't set to sprite?
I think a preset was mentioned
I am not sure when presets applied to folders runs, which could certainly be the issue
it is, the preset sets it
yeah idk if the preset is messing it up
I would try loading it as just a Texture2D just to check and simplify the setup
and also try assetdatabase
(For testing I mean)
yah there's a lot of ways to break this down and test this implementation that you can do
does loadassetatpath need file ext?
Use the same path you use for the ImportAsset
as a rule
Literally just today did it click with me why it doesn't use extensions. Been using Unity for 4+ years xD
because they're not files?
Yeah
makes sense
I had to think of it within the context of builds to realize
I enjoy never using the resources folder
I just use it because it's stupid simple
I don't want to bother with enterprise tooling unless I have to
this works :D (the loadassetatpath method fixed it)
I only ever use Resources.FindAllOfType, and that is for editor tools
yay
Thanks so much guys, ive automated some of my job now lol
Hrm, that's interesting. I wonder if that means that it's the Resources folder that hasn't recalculated its index
It's odd how those functions have nothing to do with the resources folder
anyway lesson is not to use resources in the editor
also, i fixed all the interpolation and concat mixing :)
or at all, depending on how much you hate it
😄
you still have a double //
just saying
where? i thought i got rid of it
Yeah, I was surprised when I first learned that. But it makes sense
when you concat everything together it will become /Resources//UI
found it thanks
like here
👍
ok
blame it on my lack of sleep lol
You can also get rid of the Application.dataPath
dont i need it? im using normal c# file.io, so shouldnt it not understand unity context?
All the methods can just use the same "Assets/Resources/etc" path
Yeah, it's target directory thing is set to the project folder
Its magic
It's nice not having to create so many random paths 😄
🪄 ✨
it doesnt seem to work without it
Assets/Resources
Not me, it works on my machine!
It should be the same path as the others, not /Resources
yah
I can't tell you how long I did some stupid Application.dataPath.Remove(Application.dataPath.Length - "Assets".Length) or whatever to get a project relative path before I learned I didn't need to... 🥲
epic
nice, very cool
this feels so good, i used to assign the generated icons by hand like a fkn cave man
now you are a cave man with fire
I am happy to have never known a world where I did dumb things with paths
now that we are getting exponentially more items in the game i cant do it that way anymore lol
@visual stag Just wanted to say thanks for the thing about SerializedProperties earlier being not able to be set because they are not saved to YAML. That helped it finish clicking in to place and change how I see the problem I was having! 🙂
Is there a way to convert a UnityEngine.Object reference to a string and then back by chance...?
Oh, GlobalObjectId will work I bet
Because of the change of how I am thinking about SPs a bit, it should also solve my problem I was having earlier about how to save SP values! This is great! 😄
I like how all of the methods in GlobalObjectId are tagged as slow with no alternatives
Right!? Like... why even call them slow then? Maybe just so we will all know like "Hey, these are really slow..."
I think that's why
Maybe they realized people be doing GameObject.Find(..) inside of an Update() loop and thought they should make it explicitly clear that this new API is slow.
That is all I can think of
GlobalObjectId is the correct approach, yeah
You can ToString that, then TryParse it back to a GlobalObjectId and use GlobalObjectIdToObjectSlow
The methods have "slow" in the name but that's only because (afaik) they will iterate over all objects in a scene to locate the target
That's why there are "batch" versions of them, since calling the single-object one repeatedly for a bunch of scene objects would add up in a large scene
As far as I know, the slowness doesn't apply to asset references, only scene references
That's not too hard
You can check the type
If it's a scene reference, remove it
or don't process it
ooh I see
the type is encoded in the id
smart
so it never searches what it doesn't need to
nevermind, my comment is totally useless
😄
very cool
that's a part of the editor I've never touched
Normally that type is only usable by Unity internally since the functions to use it are in C++
But GlobalObjectId is a superset of its functionality, so you can use that to reimplement it
Which I had to do in order to access objects stored in the LightingDataAsset
interesting
that could potentially be useful for my importer...
I'm wondering about ways to orchestrate having a single asset import generate many files
and keeping those files' relationship with the root asset
If you define a "fake" serializable version of an internal type, you can read/write it with EditorJsonUtility
The field name has to be the same as the class name
LightingDataAsset in this instance
that is a clever way to do that
it's trivial from there:
I used to use SerializedObject, but I had to use reflection to set its internal "inspectorMode" value
I always have compiled lambdas to access internal stuff
though usually I'm calling methods
But this approach doesn't need reflection and works better, so I ditched that
I will definitely keep that technique in my back pocket
There is a catch though
Since your field names has to match the names Unity uses in serialization, you will run into situations where the name you need to use isn't a valid identifier
I implemented a custom attribute + an assembly post processor (https://github.com/NewBloodInteractive/com.newblood.lighting-internals/blob/master/Editor/AssemblyPostProcessor.cs) that will modify the IL to rename the field after the assembly is compiled
oh, bc of the identifier indices[4]
indices[0] through indices[3] rather
public fixed int indices[4]; is just how I expose the value publicly so it's still seen as a fixed buffer
yeah
It's also annoying that Unity doesn't expose its Matrix3x4f type, only Matrix4x4f (as UnityEngine.Matrix4x4)
So I had to implement that too
It generates a tetrahedralization for more efficient light probe interpolation
fascinating
You can refresh it too: https://docs.unity3d.com/ScriptReference/LightProbes.Tetrahedralize.html
I've always wanted to sit down and learn some of the guts of rendering
just never had the drive so far
In my case this is driven by a need for it at work
Since we do a lot of custom lightmapping stuff
makes sense
(We can control the color, intensity, etc of baked lights)
that's cool
isn't it baked into a texture?
so you're modifying the texture at runtime
nope
it's still baked into a texture yes, but we don't modify the texture
It's very similar to how games like Thief or Quake did this in the 90s
you modify how it's mixed into the scene
Yeah
It's very cheap and lets us get really high quality lighting without paying the cost of dynamic lighting
so all the lights are baked as white I'm assuming
Yup
gotcha
The bake script stores their colors, sets them as white, and then bakes them
it's just not GI which means you can't move the lights
Yeah, I refer to it as "composited baked GI"
lmao
at some point I wanna do a writeup about how it works, since there's a lot of stuff involved
no kidding
unfortunately a lot of the work is actually because Unity's lightmapping API sucks
I am definitely saving your tip of accessing internal data structures
Very little is exposed, and the actual lightmapping process is hard to hook into
Most of the work involved was related to reverse engineering the engine lol
doesn't help with my need for method calls, but sure it'll come in handy
it always is 😄
Hey, a bit off topic, but do you know the diff between EditorJsonUtility and just JsonUtility?
EditorJsonUtility can modify native objects, JsonUtility only works on managed objects
i.e., EditorJsonUtility can modify anything SerializedObject can
JsonUtility can only really modify what reflection can modify
So EditorJsonUtility can change the internal m_LocalPosition value in a Transform for example, while JsonUtility wouldn't know what to do with one
well in return for that juicy information here's a class that lets you create an importer platform-specific settings group with a default tab:
EditorJsonUtility also skips validation when modifying the data, unlike SeralizedObject
Which I take advantage of
if you ever find yourself in need of making a very slick and native-esque importer 😄
because for some reason the exposed method doesn't let you create a default tab 🤔
Unity and not exposing useful APIs, name a more iconic combo
anyway I'm wondering if I can leverage globalobjectid to maintain a parent-child relationship between my imported textures and the source asset 🤔
so that I can write to the files wherever they are even if people move them
asset GUID 😉
hm
wouldn't need to be for scene objects
Then a GUID will work
cool
Well actually
GUID also won't work for sub assets
eg, if you have one asset, and the texture is a sub object of it
such as when you use AssetDatabase.AddObjectToAsset
I think that should be ok
I'm generating images, so I'd just always refer to the base imported texture
In my custom EditorWindow "BuildingCreator" I want to create a building prefab that I can then continue to tweak with a custom Inspector, to set its position and size, number of floors in the building etc.
What's the workflow for this? Instantiating prefabs seems to be done by dragging a link to a prefab into a public variable of a script component attached to a GameObject already in the scene, and then calling Instantiate using that variable as a parameter. Can my EditorWindow access that?
I made a new GameObject in the scene called "EditorInfo", attached a custom "EditorInfo" script, and made a "BuildingPrefab" variable to hold the prefab, dragged the "Building" prefab into the variable OK, and back in my EditorWindow script, I'm using this line to access it:
EditorInfo editorInfo = GameObject.FindObjectOfType<EditorInfo>();
But I'm getting the error: Assets/Editor/BuildingCreator.cs(28,9): error CS0120: An object reference is required for the non-static field, method, or property 'BuildingCreator.editorInfo'
Building Creator
Anybody know if there's something or an asset store plugin that can convert an entire GameObject into a script?
So like say there was an empty GameObject with a few cubes and text inside it
Ah wait this is the wrong place isn't it
My bad
Actually I'll make it myself if I have to
Anyways so like I said if there was an empty GameObjects with a few cubes and text inside it
How could I convert everything in that empty GameObject
Into a script that builds it
If you kind of get what I mean
Not sure exactly what you mean. Drag the topmost gameobject it into one of your data folders to create a Prefab that you can instantiate repeatedly?
If you want to build it from script you'll just have to write the code to assemble the right parts according to whatever rules you want...
There are plugins to do procgen modelling according to a node graph though, would that suit?
I don't want to jump to conclusions... but I think I have found a bug...
So.... turns out
serializedObject.CopyFromSerializedProperty("_myList.Array.size");
works fine, but
serializedObject.CopyFromSerializedPropertyIfDifferent("_myList.Array.size");
will cause the above crash...
so good news, you can indeed generate a minimal meta file and unity will happily fill it out with defaults for you
Hey, Does anyone knows if it is possible to add a button in this bar to perform custom actions?
(please ping me if you know, im going to bed i'll see tomorrow)
Does anyone know how to enable unity debugger and snippets in visual studio code, this is really bugging me 😭
I have them installed and it says they're enabled but they dont seem to work
np
(how the f*** does this work 😰 )
how did he manage to extend it lmao
iirc you can hook into the gui using shenanigans
haha i think i'm just too tried to try to understand now, i'll take a look tomorrow
looks like it takes advantage of unity's UI being based around visualelements now
mmh i see i see
I'm struggling to figure out how to record a full hierarchy undo when in the prefab editing context.
Does something look wrong with this function?
[ContextMenu("Apply Style")]
private void ApplyStyle()
{
#if UNITY_EDITOR
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null)
Undo.RegisterCompleteObjectUndo(prefabStage.prefabContentsRoot, "Apply Style");
#endif
bindings?.Apply(style); // changes a buncha properties on self and children that I'd like to be undoable
}
ah silly me. i wanted RegisterFullObjectHierarchyUndo not RegisterCompleteObjectUndo
I'm trying to build a property drawer using UIElements but getting this error:
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace EffortStar {
[CustomPropertyDrawer(typeof(AssetName))]
public class AssetNameDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var container = new VisualElement();
var foo = new Label("Foo!");
container.Add(foo);
return container;
}
}
}
Does anyone know how to address this?
I copied the structure from https://docs.unity3d.com/ScriptReference/PropertyDrawer.html
i believe editors are either all imgui or all ui elements. so if your ItemConfig's editor uses imgui it will try use OnGUI instead of CreatePropertyGUI. you're currently seeing the default unimplemented imgui for a property drawer
How do I "make an object" on the click of a custom editor button?
I found examples that do GameObject.CreatePrimitive, but I think what I want to do is spawn a Prefab
Or maybe create an empty and attach a component
@old ravine well, which are you trying to do 😄
the method varies
depending on what you're doing
I didn't make a custom editor for it
Maybe NaughtyAttributes is taking control actually
I'm not sure 😆
My goal is to create a "building entity" by clicking and dragging out a square on the ground that defines the size and placement of this building, a building pops up in that location and from there I can click on this building entity and customise its properties, like how many floors it has, etc.
So my question is: what should this bulding entity be in Unity terms. A Prefab?
is this meant for you or is this going to be a public plugin
do you want to be able to edit properties after you finalize the parameters?
or do you just want to have it be a one-and-done kind of thing
Just me :) goal is to make my life easier making my specific kind of levels.
Edit properties, this is a very dynamic thing. But baked down before gameplay
ok, I would just instantiate a prefab with a component
you can make the component editor only, so it'll get stripped out when you play
you can build the building in OnValidate but that's not super efficient, so I'd be more likely to use a custom inspector
and trigger the build there
the build code can still be in your component tho
and called from the inspector
use PrefabUtility to instantiate the prefab
check out the Undo class to help integrate undo support
That's awesome, I didn't even think of a component being editor only.
you can use component.hideFlags = HideFlags.DontSaveInBuild;
Nice, I can do that. I have a custom inspector. I might just have a button that says "update building" that you click after changing some properties
yah, or you can detect changes and update it on the fly in your inspector
Yes, I can do that but I assumed it might be slow for how I'm generating the building, but I will just do it and see how it performs
@crude relic Thanks man! Just needed some pointers, seems like there's a million ways I could go about this
@old ravine can always make auto gen a toggle 😛
Ah that's a cool idea!
looks like my idea to write the meta file by hand works & cuts out a re-import cycle
🎊
Is there any way to get mouse input event in editor, regardless of the focused unity window? I'd like to create some mouse shortcut macros.
(the shortcut editor doesn't support mouse buttons)
Here's a post from @crude relic from earlier that may be the answer, not sure, hope it helps. I can't copy a link to the post on mobile so I've copy pasted it
if you subscribe to https://docs.unity3d.com/ScriptReference/SceneView-beforeSceneGui.html you can override keyboard and mouse events that would otherwise be consumed by the sceneview
make sure to call Event.current.Use()
Hm, I didn't try that event. I tried another SceneView event and it only worked when the scene view was focused.
I'll try this one
Yeah, same issue. Requires scene view to be selected.
Ah OK, it was worth a punt
Same situation but with keyboard presses instead.. I'd be very grateful if you post your finding, regarding this later on
I gave up. From what I can tell it's not easily achieved.
I'll skip mine too for now 😆 thanks for letting me know! 👍
Hey, has anyone made any experience implementing IPreprocessBuildWithReport on a monobehaviour?
Reasoning being I've created an additional sceneloader mb, which serializes the path & guid of the scene asset during editor time and also serializes it's buildIndex - but if the build order get's changed and the object isn't selected/loaded it wouldn't get notified.
so, if anyone is interested: you can implement it with some additional #ifdef but it seems to not have access to the proper instance of the mb at that time
@barren moat you can do this if you hook into native windows functions and intercept mouse and keyboard
but you're outside of the unity ecosystem at that point
and obv it's not cross-platform
here you go @barren moat
I implemented this ages ago to get better mouse wrapping behavior a la blender
I'm having trouble with my property drawer extension. This is the error I'm getting every time i try to edit my scriptable object, and google isnt really helping me:
ArgumentException: Getting control 9's position in a group with only 9 controls when doing repaint
Anyone know what causes this, and how to solve it? I can share code if needed.
@light hearth it means you're modifying something in between the layout and repaint pass
which is a no no for IMGUI
Yeah thats what it says when i google it too. I just dont have any idea what it means lol
I dont understand what they layout pass is, nor the repaint pass, nor how Im modifying it between those passes, when this property script works for some scriptable objects but not others
I guess I have some reading to do
@light hearth here's your two second overview:
the way that IMGUI's automatic layout works is that it calls your code multiple times to draw the final inspector
first it does the layout pass
which determines all of the rects it needs
this needs to be a separate pass because some layout notions can't be finalized until after the layout item has been created
Hm I see.
after that, it goes through again and draws everything to the screen, this time using the rects that it calculated
however, if you change something about what layout functions you're calling in between layout and repaint, the saved rects generated in the layout pass won't line up with the objects you're trying to draw
it panics and throws an error
in other words: if you change state in your drawer, that state needs to be consistent at least between the Layout pass and the Repaint pass
if you post your code here I may be able to tell you how that's happening
Okay I understand that. So I need to specify which pass each instruction is in? Or repeat the instructions, once for the layout pass and then the repaint pass? This is my code: https://gdl.space/azuyunijin.cs
usually these passes are taken care of automatically
but there are certain things you can do in the code that will cause a disconnect
ok, your issue is being caused by the fact that you're trying to use layout methods inside a property drawer
on lines 51 and 54
Strange, because this works in some cases. But I believe you
for property fields, it precalculates the layout size using GetPropertyHeight
once you're inside OnGUI in the property drawer you're no longer in a layout context and you can only use GUI methods
Ahh i see
that's what's registering the controls it doesn't expect, because OnGUI doesn't receive a layout pass at all
you can check this for yourself (for educational purposes) by logging Event.current.type in the property drawer
That makes sense
you'll never see a Layout event
So OnGui is just being called in the repaint pass
yes, and also the mouse and keyboard passes
your gui functions get called many times, for any event that happens in the editor
layout and repaint are just two of them
that's why it's so easy for imgui code to become so slow
So I need to find the separate function that is called on the Layout pass and do my EditorGuiLayout things there?
there is no easy way to do layout stuff in PropertyDrawer
I would advise you stick to non-layout methods
this just means you need to calculate the rects yourself, which isn't usually too big of a deal
Hm thanks for the advice, i guess I have some reading up to do. I thought doing a simple "drop down" to display different variables would be simple.
by drop down do you mean a field toggle?
like this?
dynamic height stuff is a pain in property drawers
not impossible but still a pain
Hm maybe could work. I mean more like i have a drop down list. and when a specific drop-down entry is selected, a specific set of fields are displayed. And other drop down entries show another set of fields
I see
Thats sort of what my propertydrawer does now. But it doesnt work for some scriptable objects
yeah, complex inspector stuff is outside the scope of propertydrawer
you would need to specify the heights each of your dropdown fields need to take up
in your getpropertyheight method
Ah rip. Thought this was such a common problem that there would be some go-to solution that most people use
most people use custom editors
lmao i legit thought that was what property drawers were
no, property drawers are for specific types or attributes
But property drawers are more for individual fields
to be drawn inside an editor
or htat, yeha
yes
Well I appreciate the help, now I have a starting point of where to look.
np
@light hearth https://github.com/vexe/VFW this package has some fancy features including better property drawers
Thanks ill check it out. Also found this source that does something similar to what i want to accomplish : https://www.youtube.com/watch?v=BKaIn3hIuyo
looks like that video uses a custom editor, rather than a property drawer
if you want your PassiveEffect drawer to be used in many different classes this won't work for you
Oh yeah, thats correct. thanks for the heads up.
My mind is drawing blank, is there a way to only iterate the children of a serialized property besides comparing propertyPath?
Well lets say there is
_floatValue
_myClass // I only want to iterate the direct children of this (foo, bar)
_myClass.foo
_myClass.bar
_otherFloatValue
I can do while (property.Next(true) && property.propertyPath.StartsWith(basePropertyPath))
But wondering if there was a nicer way
ooh, good idea. I forgot it was a thing
while( Next && depth > startDepth )```
Hey, does anyone know of a page where I can find all the available EditorGui controls with screenshots? Sometimes I'm trying to find a specific thing, but I have to try a few because there are no screenshots of what it looks like anywhere
would Window/UI Toolkit/Samples be helpful?
maybe? I actually found what I needed luckily 🙂 (All I wanted was a menu to popup from a generic button, and that control is literally called GenericMenu hahaha)
who knew 🙂
I am trying to find all overridden properties on a prefab variant, as well as their original values on the source prefab so that I can revert the overrides whose values are unchanged. I've been fumbling around the PrefabUtility API all day and am struggling. Does this sound possible?
So as an example, if you have a prefab variant that changes an images color to white, but the source prefabs image color is also white, I wanna detect that and revert the redundant override
How do I instantiate a Prefab from within an EditorWindow?
The only way I know to instantiate anything is by making a public variable on the object in the scene that holds a reference to the prefab, this variable is passed to the "Instantiate" function. But the EdtorWindow script doesn't exist in the scene so we can't set its public variables in this way.
You can load prefabs with the AssetDatabase or write some gui for an object field within the window
Thanks 🙂 I will look into AssetDatabase because it should be the same prefab every time
Hope someone helps with your question
Oh well you happen to be in luck be cause literally just yesterday I needed to do this as well! PrefabUtility.GetPropertyModifications(targetObject) is what you want
It will give you an array of PropertyModification which contains a string for the value and a string for the property path
Also has an UnityEngine.Object field for object references
Hey! How so I have an enum of states and each of them has different values which works as intended, but how would I make a List above all this which would give the state enum dropdown list again?
Work around is adding the script multiple times like this:
Sorry, could you explain this a little more?
so I have public struct HorrorData containing enum and some variables
then I have a class Horror with the list of HorrorData
So what's the issue?
and in my HorrorEditor I have this
this way it makes the list
but this part doesnt do anything
before I added the list it worked and filtered only the variables that I needed but now after I added the list this is completely ignored and it shows all the variables
Did your Horror class exist before this?
Could I see the entire HorrorData script?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Horror : MonoBehaviour
{
public List<HorrorData> hor = new List<HorrorData>();
}
[System.Serializable]
public struct HorrorData
{
public enum HorrorEvent
{
DisableAtStart,
DisableMovement,
MoveObject,
Teleport,
LightOnOff,
Jumpscare,
LookAt,
PlaySound,
DropObject,
Levitate,
ThrowObject,
EnableOtherTrigger
};
public HorrorEvent state;
private GameObject player;
//Disable At Start
public bool disableAtStart;
//Disable Movement Settings
public float delayBeforeMovingAgain;
//Move Object Settings
public MovableObject movableObject;
public float delayMoveObject;
//Teleport Object Settings
public MovableObject teleportObject;
//Lights ON/OFF Settings
public bool lightsOnOff;
//public List<Light> Lights = new List<Light>();
//Jumpscare Settings
public Image jumpSImage;
public float stayOnScreenFor;
//Look At Settings
public GameObject camera;
public Transform lookAt;
public float lookAtDelay;
public float damping;
//private Vector3 lookPos = new Vector3();
private bool startLook;
//Play Sound Settings
public string clipName;
//Drop Object Settings
public GameObject dropObject;
//Levitate Objects Settings
//public List<FallObject> LevitateObjects = new List<FallObject>();
public float forceUp;
public float forceDown;
public float delay;
//Throw Object Settings
public FallObject throwObject;
public float force;
//Enable Other Trigger Settings
public GameObject otherTrigger;
}
this is the Editor
Lets say I move it back and comment out the list
public class Horror : MonoBehaviour
{
//public List<HorrorData> hor = new List<HorrorData>();
public enum HorrorEvent
{
DisableAtStart,
DisableMovement,
MoveObject,
Teleport,
LightOnOff,
Jumpscare,
LookAt,
PlaySound,
DropObject,
Levitate,
ThrowObject,
EnableOtherTrigger
};
public HorrorEvent state;
private GameObject player;
//Disable At Start
public bool disableAtStart;
//Disable Movement Settings
public float delayBeforeMovingAgain;
//Move Object Settings
public MovableObject movableObject;
public float delayMoveObject;
//Teleport Object Settings
public MovableObject teleportObject;
//Lights ON/OFF Settings
public bool lightsOnOff;
//public List<Light> Lights = new List<Light>();
//Jumpscare Settings
public Image jumpSImage;
public float stayOnScreenFor;
//Look At Settings
public GameObject camera;
public Transform lookAt;
public float lookAtDelay;
public float damping;
//private Vector3 lookPos = new Vector3();
private bool startLook;
//Play Sound Settings
public string clipName;
//Drop Object Settings
public GameObject dropObject;
//Levitate Objects Settings
//public List<FallObject> LevitateObjects = new List<FallObject>();
public float forceUp;
public float forceDown;
public float delay;
//Throw Object Settings
public FallObject throwObject;
public float force;
//Enable Other Trigger Settings
public GameObject otherTrigger;
}
I think I see the issue
this works as intended but I can only select one enum
😲
You're drawing the properties of HorrorData with the custom editor
But since HorrorData is a struct and not a Monobehaviour instances of it only appear within the Horror data class, which doesn't have a custom editor
ooh I see
I think you have to draw the properties accessing them through the Horror class
Since there are no instances of the HorrorData struct outside of the Horror class
like move everything from HorrorData to Horror?
Not exactly
this works and it draws the correct properties but then I'm not sure how to make a list out of that
If you accessed the properties THROUGH your Horror class then it should work fine
I'll try to give an example
that would be awesome, thank you very much
Will VisualElement.MarkDirtyRepaint also mark the children as dirty then repaint them all? I didn't see this mentioned in the docs anywhere
It's a little trickier than I expected
Still trying
@zenith estuary I just used your EditorJsonUtility trick for the first time -- thanks again for sharing that, it's great!
It might not be possible with the current system you have
Since you don't have access to the variables inside of HorrorData as SerializedProperties, it's impossible to custom draw them
right
The SerializedProperties for those variables are never created since that's not the object being inspected
Not sure
I just recently started messing around with editor stuff a few weeks ago, and while I have learned a lot I'm definitely no expert at this stuff
Well I started 7 hours ago 😄
Heh yeah
thank you for the help anyways I really appreciate it
I'm not sure if you could write a custom inspector for your HorrorData class
Change it to a class instead of a struct and you might be able to
Personally I would see if there's a way to make a custom inspector for you HorrorData class first
You could also try using a list of scriptable objects
I haven't thought about that, that could be an option
Oh actually, you could potentially put your HorrorData class inside of the other one, and see if you have access to the vars that way
yeah
Try something like this:
public class Horror : MonoBehaviour
{
public List<HorrorData> data = new List<HorrorData>();
public class HorrorData
{
//Your data
}
}
And then see if you're able to access the properties of HorrorData through the custom inspector
can't access them that way :/
wait I can
You can??
with System.Serializable
Try to access the SerializedProperties through the editor class though
weeeell yeah that doesnt work 😄
Try using Editor.CreateEditor on each of your HorrorData classes then try accessing the properties
I'm a bit out of what I know at this point
From what I've found online though this should be what you're looking for https://docs.unity3d.com/ScriptReference/Editor.CreateEditor.html
you have done more then enough, thanks a lot
I'll go and play with that documentation now hahha
You can make a serializeable custom class with your enums in it
then instantiate the custom class as serializeobject as array
you don't even need customEditor for that
We're trying to figure out how to access the SerializedProperties on the HorrorData class through the Horror class, do you know how?
My curiosity is piqued now, what'd you use it for?
Marshalling the internal BuildPlatform class to my own for the purposes of implementing a 1:1 platform specific settings box for my inspector
without it I'd need to build the conversion into the lambda
which is annoying
Yeah, and SerializedObject is also a bunch of effort
Yeah
If you wanted to use SerializedObject you'd have to use a wrapper ScriptableObject or something
the platform specific settings methodology is really convoluted
I'm just digging into it in the reference source
they use a bunch of proxy objects and stuff
Editor code is constantly a mess I swear lol
all to make the editor experience smooth and limit what they need to serialize
it really is
Agreed
Although I really don't know enough to be efficient with it anyway
Howdy Mech, tried doing a build using this library but there appears to be an issue with my version in "UHashSet" line 357,
Assets\_Assets\Scripts\Utilities\Runtime\UHashSet.cs(357,44): error CS0103: The name '_serializedItems' does not exist in the current context```
is there an issue with just changing this to "_serializedValues" as that appears to compile, or is _serializedItems a different form of object altogether and this shouldn't be happening?
Woops, I had refactored something but didn't change it in the #if UNITY_EDITOR. Fixed
all good, glad it was a quick fix.
Anyone have experience with Playfab? Trying to see if its possible to send a password recovery email to someone given their username. I dont want users to have to login with email or type it in for recovery. Is it possible to find their email based on their username? I tried using GetAccountInfo but it says u need to be logged in to make the api call, which obviously user will not be since they need their password to login
I doubt this is the rigth channel for that
Whats the right channel then? i figured playfab is closer to an extension than anything else in the list on the sidebar
This channel is for developing extensions
Not questions about random plugins
Playfab's official resources are your best bet, but you can try in #archived-code-general I guess
Okay i didnt think it fit in code general but i'll try that. There's nothing i can find on the documentation about this
They probbaly have a forum or a discord themselves for questions
anyone know how to pass data from Port to Port in Graph View?
there is a forum but none of my questions have been asked there and the ones i submitted havent been either
I'm looking for a way to see the Scene as a node graph, to see the relations between every gameobjects and their monohabeviours
and add/remove relations between those behaviour properties using node links
anyone know something like that ?
If a script is in the Assets/Editor folder, shouldnt it automatically NOT compile with a build? Do you absolutely HAVE to encapsulate every Editor script in a Editor folder with #if UNITY_EDITOR for it to exclude from a build?
If you are not using Assembly Definitions, things in the editor folder are not included in the build.
Ah I see, is there a way to make every script of a assembly definition get excluded or is it just best to delete the assembly definition file when I want to make builds?
Awesome, that might be what im looking for - thanks!
You can do so, very restrictively via .userData note, it will be object type so the casting is required
not from/to Port but to Nodes specifically
if you required to have some function to detecting Ports for example then that depends on your implementation, but you can still use userData as a self-contained container
you can sorta see it in action in here https://github.com/Unity-Technologies/UIElementsExamples/blob/e940d1c9dddfe99fd500c9f34f4801856ad37f18/Assets/Examples/Editor/E17_Transitions.cs
just to note, I said sorta 🙂 bcos the example is not for graphview, but it still applies
either way, you can do this without it, as filtering connected ports should do the job for most use cases
another example from my graphview's node
//Associate VParentNode class upon creation
vnode.userData = new VParentNode(vnode.VNodeId) as VParentNode;
Hi, I'm constantly forgetting to assign serialized Fields after creating/refactoring scripts. Since Unity doesn't seem to have a "require"-feature for fields (or does it?), I'm thinking about writing an extension that checks all serializefields in my scene/prefabs to not be null, unless i specifically annotate it to state otherwise in my code. Does somebody know if such an extension exists or how I would approach building my own? Maybe some kind of hook that's executed after the compile process, where I can iterate over all scripts in the Scene
You would want to create a script that iterates over your objects, collects the fields, and checks if they're null
Excluding any that contains your attribute
You can do this using reflection
I would also cache your class types so you don't repeat work
@south beacon
Okay, I'll give it a try. Thanks!
ok so I think I figured out a way to transfer ports-
how can I like
get the custom attribute of a variable
public string stringName;
void OnEnterNode()
{
string = { variable from the Port attribute };
}```
something like this
I have the Port with a constructor
which takes in some variables
and then another variable that is assigned sometime else, outside of the constructor
You need to get the FieldInfo in order to get the attributes
A simple example that would work for the above code:
oh?
var attribute = GetType().GetField(nameof(stringName)).GetCustomAttribute<PortAttribute>();
Ideally you would want to cache this stuff somewhere, since you don't want to constantly be using reflection
For editor code, Unity also has a TypeCache class
You can do TypeCache.GetFieldsWithAttribute<PortAttribute>() to iterate over every field in your code with that attribute
I'm looking to have a Rightclick menu that creates a new Prefab based on an existing Prefab? Whats the best way to go about doing this?
yeah, this is a pain
I have to somehow get variables, when all I know is the port that corresponds to them, which is kept inside their attribute
I have literally no idea how to do such a thing-
the graphview is just a representation of your data, you can check which port connected to which...
literally just a graphical representation...
yeah but the way I'm telling it to create ports is by making variables, assigning a custom attribute, and then get all of the variables with that custom attribute and run some logic to create the ports in a NodeView script
the issue however, is that I need to get the variables from an output port from Node A to the input one on Node B
it's really hard to explain-
uhh
variable has a custom attribute
custom attribute of that variable has a reference to it's corresponding port that gets assigned when I create it
and then I need to get the variables that correspond to those ports
the ports are store in the custom attribute of those variables
and I somehow need to get the variables
this is the function to create ports:
{
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
MemberInfo[] members = node.GetType().GetMembers(flags);
foreach (MemberInfo member in members)
{
if (member.CustomAttributes.ToArray().Length > 0)
{
PortAttribute attribute = member.GetCustomAttribute<PortAttribute>();
if (attribute != null)
{
PortAttributeInfo info = new PortAttributeInfo(member, attribute);
Port newPort = InstantiatePort(Orientation.Horizontal, info.portAttribute.direction, info.portAttribute.capacity, info.portAttribute.dataType);
newPort.portName = "";
info.portAttribute.correspondingPort = newPort;
Debug.Log(info.portAttribute.correspondingPort.userData);
Debug.Log(info.portAttribute.correspondingPort);
if (attribute.direction == Direction.Input)
{
inputPorts.Add(newPort);
inputContainer.Add(newPort);
}
else
{
outputPorts.Add(newPort);
outputContainer.Add(newPort);
}
}
}
}
}```
it just takes in a Node, gets all the variables that have an attribute of PortAttribute, and creates a port based on the values from that attribute
This line is where I tell that variable which port corresponds to it
info.portAttribute.correspondingPort = newPort;
so now I have this function where o is the parent and c is the child Node
//Assign userData to parent first using the Ports
c.userData = o.userData;
AddElement(edge);```
You can optimize that a bit by using TypeCache, which will avoid a lot of the work involved in scanning types for attributes etc
Though it depends on the Unity version you're on
2021.2
You can use it then
yeah
I will optimize it after
I'm confused, why is there an issue
Unfortunately there's no GetMembersWithAttribute, only fields and methods
If you're building ports you already have the fields
So there's nothing for properties
because I can't figure out how to get the variables that correspond to those ports
because the ports are stored inside of the attribute corresponding to that variable
so I have 2 ports, start and end, which I need to assign data to
this is where I keep the port reference for the variable
yeah I just have no idea how to code this all
So your PortAttribute describes the data that you want to receive in the stringToDebug field?
I can get the node from the start port and the end port
it describes the port that I assign the variable to
the correspondingPort variable is referenced in the CreatePort() function I posted earlier
It's best to not store Port in the attribute itself
then where?
Attributes are for "constant" data
That makes no sense
You would store it elsewhere, in a cache or some other location
A static dictionary could work
Yeah, you should make a list of connections on your graph object
With start ports and end ports
Or something
Or a dictionarry
a dictionary might work
Also, is DataType always supposed to be set to the field's type?
uhh
[Port(...)]
public T Something;
should it always be typeof(T) in this example?
Yeah that's what I was about to mention
But wanted to be sure that's what the data is meant to be
Yah
Yeah you can't really write data to attributes
And if you can then you shouldn't
The attribute should probably be:
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public sealed class PortAttribute : Attribute
{
public Direction Direction { get; }
public Capacity Capacity { get; }
public PortAttribute(Direction direction, Capacity capacity)
{
Direction = direction;
Capacity = capacity;
}
}
And then you can do:
foreach (FieldInfo field in TypeCache.GetFieldsWithAttribute<PortAttribute>())
{
var attr = field.GetCustomAttribute<PortAttribute>();
// set up the port for this field
}
ok my brain is just, fried
Your dictionary could be Dictionary<FieldInfo, Port>
Are you trying to serialize connections in your graph
I really don't know how to do any of this
I have variables with attributes, a script takes the attributes and creates the ports, and then I need to somehow make the variables in the second Node be equal to the ones in the first
like
You only need to do that when you're executing the graph
yes
and while it's running
I don't know how to tell it to take the variable from the port it's connected to
That's what I said
because the code has no idea what ports correspond to which variables
That's what your scanning code is supposed to be setting up
ok then in what way should I keep track of which ports correspond to which variables
Make a port class that contains a memberinfo
Create a port for each port attribute
Assign all the relevant fields
Save it in a list or dictionary
Tada
You now have a list of ports corresponding to variables
sometimes I realize I am not very smart lmao
(also it should be FieldInfo and not MemberInfo since you don't seem to be using this with properties or methods)
Yes