Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Suggestion / Idea  Problem with the Obi Solver Structure
#4
Hi! 

Thanks for the detailed answer and the code snippet!

About the architecture, I understand your arguments, but I may have some things to add:

Quote:- This design is identical to Unity's UI architecture: their Canvas is our Solver, and UI panels our Actors. It's tried and tested, and for most users, a familiar architectural design.


While I agree that it is familiar, the UI architecture is quite problematic the new prefab architecture, and I'm not sure the two are really comparable: to me, actors like obi actors are meant to be flexible in the hierarchy so the user can do whatever fits his usage. The UI architecture itself is quite criticized in Unity's forum, so I'm not sure it's necessarily the best example.
In my personal case, it is quite problematic.  Now I understand I can just call AddToSolver and ignore the architecture, but couldn't I just have an ObiSolver field so I could manually set it in the inspector like it used to be, and that would be found by default in the parent on Reset?

Quote:This is arguably more confusing, verbose and error prone (most people forgot to call AddToSolver()) than simply reparenting a transform. 

So does it means that Obi will automatically add the actor to the solver as soon as it's reparented? What if I unparent it, what happens then? That's also confusing to me then: nothing indicates a runtime handling of this here, and if there is it's not necessarily easy to understand (at least to my standard)
Quote:Allowing an actor to work only when parented to a solver results in an intuitive way to transform the entire thing (that is impossible to set up wrong)

I understand, but that also means that you can't configure your obi actor with your own logic and objects together under prefabs: I use obi rope together with cable connectors that can drag and drop, and a whole logic to pool them and save/load them: it makes much more sense project-wise to have the obi actor part of the same prefab, and it also makes it much easier to debug: I suppose I could change the parent of the rope only on runtime, but I find it confusing.

Quote:In both cases you have a reference to an object, and the work you do (both in editor and scripting) is basically the same: you have two components, and one of them must have a reference to another object. 

It is not similar: in your case you are required to:
  1. Open your obi actor inspector, and lock it
  2. Open a second inspector for your object that requires a reference to an attachment
  3. drag and drop the component on the second inspector
  4. Unlock / close the inspector
It's just really not a convenient workflow. Moreover, it doesn't scale well: let's say I would have 20 attachment on one rope, that means 20 components on the same objects: it's both very hard to navigate and also not readable.

Quote:With your solution, attachments could be pretty much anywhere in the scene, and having to look for them all over the place doesn't sound nice


This is really easy to do with the custom search on the scene or using the new Quick Search feature. I would also say that with a proper naming convention, it's really easy to find.
On the contrary, trying to track which component is problematic in a list of 20 or so on the same game object is much harder, because the object pinging won't work, and the reference fields won't indicate which component is used.

Quote:This is the same design most existing Unity components have: if a component primarily acts upon or modifies an object, it should be added to that object. Allowing it to be added to any object in the scene, and then referencing the actual object it works on it's a bit messy imho. By your logic, it should be possible to add joints to any object, and have them expose two references to the objects it joins. Or allow MeshRenderers to have a reference to the transform used to transform the mesh.


For me this is a tad of a semantic consideration here: if my component is on the attachment, then the game object has a component performing a certain action. it acts upon the same object too in the sense that it adds functionality to it.


It is in any way less messy than having multiple components of the same kind of a singular objects: I try to make my game objects respect the single responsibility principle as much as possible, and I find it much easier to operate and navigate, especially that it allows you to use all the navigation features of Unity (pinging, logging, searching...) and to apply any naming convention you may want (contrary to adding many components to the same object since now the object has a lot of responsibilities and a single name, and no ability to ping it or log it properly)

On the top, you could have read-only inspector fields on your ObiActor component that show all the current attachment, so that it is easy to track them from the editor: this way you'd have the best of the two worlds.

One more thing worth mentioning here too: 
Unity 2019.3b with no domain/scene reload option on crashes with a 100% repro when trying to have an obi rope placed not under an obi solver.

I also think that your awake code should look for the root object first because in my case the rope is only one of many game objects in my prefab:

Code:
       protected void Awake()
       {
#if UNITY_EDITOR

           // Check if this script's GameObject is in a PrefabStage
           var prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetPrefabStage(gameObject);

           if (prefabStage != null)
           {
               //find the root object in the prefab
               Transform transformToReparent=gameObject.transform;

               while (transformToReparent.parent != null)
               {
                   transformToReparent = transform.parent;
               }

               // Add our own environment root and move it to the PrefabStage scene
               var newParent = new GameObject("ObiSolver (Environment)", typeof(ObiSolver),
                   typeof(ObiLateFixedUpdater));
               newParent.GetComponent<ObiLateFixedUpdater>().solvers.Add(newParent.GetComponent<ObiSolver>());
               UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene(newParent, gameObject.scene);
               transformToReparent.SetParent(newParent.transform);
           }
#endif
       }
and would that be enough to dynamically switch solver?
Code:
  public ObiSolver solver
       {
           get { return m_Solver; }
           set
           {
               if(m_Solver)
                   RemoveFromSolver();
               m_Solver = value;
               transform.SetParent(m_Solver.transform);
               AddToSolver();
           }
       }
Reply


Messages In This Thread
RE: Problem with the Obi Solver Structure - by Bill Sansky - 22-11-2019, 02:18 PM