My script extracts all child objects from a parent object. I need to assign materials individually to child objects or material to all objects via parent object.
Currently when I change a child material, all other child object materials get changed aswell.
How it looks in Unity when I change a child material
Here is my code
if (includeChildObj == true)
{
EditorGUILayout.Foldout(includeChildObj, "List of Child Objects", includeChildObj);
for (int i = 0; i < Geometry.getChildNames().Count; i++) // loop through all child objects
{
GUILayout.BeginHorizontal();
GUILayout.Label(Geometry.getChildNames()[i]); // display object name
EditorGUILayout.PropertyField(serializedObject.FindProperty("SelectMaterial")); // find an enum which allows the dropdown list
GUILayout.EndHorizontal();
serializedObject.ApplyModifiedProperties();
}
}
How is see it is that inside the FOR loop, for every Geometry object, I need to instantiate a new object of the corresponding enum. I am not sure how to do this as I am using CustomEditor not Monobehaviour.
Thank you!
It appears that you are referencing the same serialized object in each iteration of your for loop. So there's only one value being read and assigned to in each iteration, which explains the behaviour you're seeing.
It's not clear to me what your requirements are, but perhaps you need multiple instances of that serialized object, one per Geometry child?
Related
I have a folder, Items, that contains prefabs with the class attached, what I want to do is make an array full of these prefabs in order to compare their ID numbers, a string inside the item class, with the ID numbers from a database to put these prefabs into an inventory array, I hope this is enough detail.
This is what you probably need.
public List<GameObject> prefabsWithClassOnThem;
public GameObject CheckTheID(string ID)
{
foreach (GameObject go in prefabsWithClassOnThem)
{
if(go.GetComponent<ItemClass>().getID() == ID){
return go;
}
}
return null;
}
prefabsWithClassOnThem - the name speaks for itself. It is the list of prefabs you will have to put manually into the list. Then you add your script to a script manager (or any object you feel like) this is how it will look like:
Click on the arrow, write in wanted size and put all the prefabs manually.
CheckTheID - method, which will check for a prefab with the ID you give for this method.
ItemClass - the class, you were mentioning in your question. The class which holds the ID of prefab, and has method GetID().
You will want to call this method in your addToInventory method or something like this.
If you want to check if object was instantiated before, just create additional boolean parameter in ItemClass which will hold true if it was instantiated (you will have to change it for the first time you instantiate one of the prefabs).
Every time you want to create unique item, just check the boolean and thats pretty much it.
Sorry for messy language.
How to get ObjectId of the recently modified object?
I add some polyline to the drawing. Each one is the same. When one modifies the other, they must also be adjusted to the changes. I need to exclude from the list of objects that need to be updated, the object I just modified. I can not find the answer.
Example:
I have some polyline. When creating them, an event handler is added (ObjectId of each object is added to NOD). At the moment of modifying one of them, the function assigned to the modification will loop through all objects stored in NOD. When the length is changed other objects must also do so. Initially I want to do that the rest will be removed and replaced with a modified copy of the object.
Here I need to access the last modified object to be able to skip it while modifying other polyline. At the moment, the program ends and I think this is a problem because I'm trying to convert the polylines to the same one.
If I understand your problem correctly, what you need is a dynamic exclusion list. A Hashset<ObjectID> instance will serve you well, as ObjectID is a struct (i.e. a value type). See this tutorial:
HashSet is an unordered collection that contains unique elements. We can apply various operations on a HashSet like, Add, Remove, Contains etc.
Once a polyline is modified by user, I am assuming an event triggers your process to go ahead and modify all other polylines in your NOD. To utilize your exclusion list, add a private field to the class that contains your Command Methods:
private static HashSet<ObjectId> exclusionList = new HashSet<ObjectId>();
Make sure to add the ObjectID of the polyline that the user modified to the exclusionList right away:
exclusionList.Add(modifiedObjectID);
The Add() method returns true if the list does not contain the objectID you tried to add, and adds it to the set. It will return false if the set already contains the ObjectID. This is the key to solving your issue. You add each entity to the exclusion set so that each one is only modified once per cycle. Also, since you already added your original polyline's ObjectID to the set, it will never be modified in the loop. After the loop ends, clear the list and wait for the next time the user modifies an entity.
In your loop that cycles through your MOD, do the following:
public void ProcessEntities()
{
foreach(DBDictionaryEntry obj in MyNOD)
{
//Add each objectID to your exclusion List
//if it's already there, everything inside the if statement is skipped!
if(exclusionList.Add(obj.Value))
{
//do your object modification here
}
}
//All entities have been processed now
//clear the list and wait for the next event
exclusionList.Clear();
}
Background
I have a list of generic objects. Each generic object has a specific field I need to remove.
I create the list like this.
list = new List<Object>();
list = JsonConvert.DeserializeObject<List<T>>(OutJson, new BooleanJsonConverter());
However i need to then remove a item from every object in that list. However i don't know how many or what objects are in the list. I do know that there will always be a field that i need to remove however.
Pseudocode
I think I need to do something like this, but in a generic way.
//Loop through list objects, and for each object, loop through its
//properties. If any of the properties match a string, remove
//that property from the object.
foreach (var object in list)
{
foreach (var item in object)
{
if(item.ToUpper() == "SpecificKey")
{
list.Remove(item);
}
}
}
Question
How do I loop through the generic object in a list and remove a specific item if it is present?
I think to complete this, it's better to mark the objects as dynamic.
Then this would work.
List<dynamic> list = JsonConvert.DeserializeObject<List<T>>(OutJson, new BooleanJsonConverter());
list.RemoveAll(x=>x["SpecificKey"]!=null);
I have a list of generic objects. Each generic object has a specific field I need to remove.
If you're trying to access a specific property on an objection, you can use reflection. See the answer here:
Get property value from string using reflection in C#
i need to then remove a item from every object in that list. However i don't know how many or what objects are in the list. I do know that there will always be a field that i need to remove however.
Your pseudocode is code is confusing, but it seems like you're just trying to remove a child from a parent object. If that is the case, and the child is a complex object, then set it equal to null.
If you mean to say that you need to any object from the list that contains a property that has the specified property name, then you should know that you cannot remove items from a list while iterating through it using foreach. See the answer here:
C# List - Removing items while looping / iterating
I have a collection that populates a treeview, and I want to add functionality that allows a node to be added with custom properties. Would the best way to go about it to clone the selected node and then edit the properties from there, or to add a completely new blank node?
The following method is how I'm currently trying to add nodes.
public void add()
{
hClass clone = new hClass();
clone = SelectedNode;
Topics.Add(clone);
}
And then I call the method via a command.
It really depends on what you do with these nodes and which pieces of code an access them. Eric Lippert wrote a blog post focused on immutable collections which might shed more light on your problem.
The collection is a set of references (pointers) to the nodes. If you assign an existing instance of hClass to the collection, a change to the instance will be visible in every place that can access it. If you're using it in a WPF GUI, read about Responding to data source changes
I have a list of StockMultibuy items, and am building a list of those items. Some of the items in the list I want to have different properties than existing items, and so I tried to create a new instance of the item, changed the property that I wanted, and then added it to the list. I wasn't expecting this to update items that were already in the list. Is this expected behaviour? Is there anything I can do to overcome this?
Thanks
StockMultibuy aNewItem = StaticLists.GetStockMultibuyForBarcode(sBarcode);
// If we've got enough items to qualify, then add a free item
if (Reward.StockItemsTaken.Count % (Reward.FreeWhenQualified + Reward.QualifyingQty)
== Reward.QualifyingQty)
{
aNewItem.PromoPrice = 0;
}
// Save this for later so that we know we've added a regular item
else
{
aNewItem.PromoPrice = Convert.ToDecimal(aNewItem.Sell);
}
Reward.StockItemsTaken.Add(aNewItem);
You're not adding several different items to the list, you're adding the same exact item several times and modifying it each time.
Classes in C# are reference types; that means each variable doesn't hold the data for the object itself, it just hold onto a reference to where that object is. Assigning an object to another variable doesn't create a new object, it just copies the reference to that same object.
The issue is that you should be creating a new object (i.e. using the new keyword) each time you go to add a new item to the list.
From the looks of your code it would seem that StaticLists.GetStockMultibuyForBarcode(sBarcode) isn't returning a new item each time; it's just returning the same item, or at the very least one of the existing items. You should be creating a new item, copying some of the values of that item over (if that's your intention) and then adding that new item to the list.
It is expected, it will update because it is a reference. I would just make a copy of the object or clone it if you can.