Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by CoatsinkPC · Mar 16, 2013 at 08:28 PM · inspectorserializationruntimehandles

Handle modified variables being temporarily reset at runtime

(I asked this same question in the forum before finding this section. I apologise if that breaks any rules and will remove the offending duplicate if necessary)

edit: here's the link to the forum thread http://forum.unity3d.com/threads/174300-Variables-modified-by-handles-are-being-temporarily-reset-at-runtime

Hello, long-time lurker, first time poster. I've tried my best to get as far as I could with existing documentation and support that I've found online, but now I am officially stuck! I'm sure I'm missing something fundamental here, so lets see how badly I'm failing.

What I'm trying to do:

I'm creating an editor extension that will include the ability to quickly add and modify box and sphere colliders to aid in camera tracking.

I've made prefabs of these objects with custom inspectors to modify their size and shape, among other settings. I've also written some custom camera facing gizmos to display their size and shape to the user while they are testing their game. The objects also have handles that will allow the user to modify the collider's size and shape from within the scene view, with the intention being that they can quickly make modifications without having to look over to the inspector.

The actual problem:

My problem is that, while these handles will successfully modify the variables I want, updating the gizmos to show the updated information, the moment I press play, the gizmos reset to the last known setting made by the inspector, completely ignoring the handle modifications.

The variables aren't forgotten though, and when I select the object again in editor mode, the gizmos instantly revert to their correct size and shape.

This is only happening when the variables are modified by the handles. when they are modified by the custom inspector, the whole thing works as intended.

http://i.imgur.com/OpNXTyz.jpg http://i.imgur.com/2udYF93.jpg http://i.imgur.com/Et1duGu.jpg http://i.imgur.com/qkug9lx.jpg http://i.imgur.com/tUPtTE6.jpg

Here is the code I'm using. It's based on this star tutorial.

The data storage, retrieval and gizmo drawing script

 using UnityEngine;
 using System.Collections;
 
 [ExecuteInEditMode]
 public class TestData : MonoBehaviour {
     
     public Vector2 innerRect = new Vector2(7, 4);    //Area data
     public Vector2 outerRect = new Vector2(10, 5);
     
     public float Radius = 0.5f;        //radius data
 
     
     //Set Zone Data
     public void UpdateTestData(){
         
         ClampValues();
         
         var boxInner = GetComponent<BoxCollider>();
         boxInner.size = new Vector3(innerRect.x, innerRect.y, innerRect.x);
         
         var boxOuter = transform.Find("Outer Box").GetComponent<BoxCollider>();
         boxOuter.size = new Vector3(outerRect.x, outerRect.y, outerRect.x);
         
         var sphere = transform.Find("Outer Sphere").GetComponent<SphereCollider>();
         sphere.radius = Radius;
     }
     
     //Get Test Data
     public void GetTestData(){
         
         var boxInner = GetComponent<BoxCollider>();
         innerRect = new Vector2((boxInner.size.x > boxInner.size.z) ? boxInner.size.x : boxInner.size.z, boxInner.size.y);
         
         var boxOuter = transform.Find("Outer Box").GetComponent<BoxCollider>();
         outerRect = new Vector2((boxOuter.size.x > boxOuter.size.z) ? boxOuter.size.x : boxOuter.size.z, boxOuter.size.y);
         
         var sphere = transform.Find("Outer Sphere").GetComponent<SphereCollider>();
         Radius = sphere.radius;
         
         ClampValues();
     }
     
     //Clamp Values to reasonable limits
     void ClampValues() {
         
         //Inner Bounds
         innerRect.x = (innerRect.x < 0.1f) ? 0.1f : innerRect.x;
         innerRect.y = (innerRect.y < 0.1f) ? 0.1f : innerRect.y;
         
         //Outer Bounds
         outerRect.x = (innerRect.x >= outerRect.x) ? innerRect.x : outerRect.x;
         outerRect.y = (innerRect.y >= outerRect.y) ? innerRect.y : outerRect.y;
         
         Radius = (Radius < 0) ? 0: Radius;
         
     }
     
     void onEnable(){
         UpdateTestData();
     }
     
     void Reset () {
         UpdateTestData();
     }
     
     void OnDrawGizmos(){
         //Drawing a custom rectangle to represent the zone bounds
         
         Vector3 currentCamRot = Camera.main.transform.forward;
         Quaternion lookRot = Quaternion.LookRotation(currentCamRot);        //Get the camera-facing angle
         
         //Draw inner bounds
         Gizmos.color = Color.red;
         //Get the 4 corners of the area
         Vector3 PointA = new Vector3((-innerRect.x/2), innerRect.y/2, 0f),
                 PointB = new Vector3(innerRect.x/2, innerRect.y/2, 0f),
                 PointC = new Vector3(innerRect.x/2, (-innerRect.y/2), 0f),
                 PointD = new Vector3((-innerRect.x/2), (-innerRect.y/2), 0f);
         
         //Draw the 4 edges of the area
         Gizmos.DrawLine(transform.TransformPoint(lookRot * PointA),  transform.TransformPoint(lookRot * PointB));
         Gizmos.DrawLine(transform.TransformPoint(lookRot * PointB), transform.TransformPoint(lookRot * PointC));
         Gizmos.DrawLine(transform.TransformPoint(lookRot * PointC),  transform.TransformPoint(lookRot * PointD));
         Gizmos.DrawLine(transform.TransformPoint(lookRot * PointD), transform.TransformPoint(lookRot * PointA));
         
         
         //Draw outer bounds
         Gizmos.color = Color.yellow;
         //Get the 4 corners of the area
         PointA = new Vector3((-outerRect.x/2), outerRect.y/2, 0f);
         PointB = new Vector3(outerRect.x/2, outerRect.y/2, 0f);
         PointC = new Vector3(outerRect.x/2, (-outerRect.y/2), 0f);
         PointD = new Vector3((-outerRect.x/2), (-outerRect.y/2), 0f);
         
         //Draw the 4 edges of the area
         Gizmos.DrawLine(transform.TransformPoint(lookRot * PointA),  transform.TransformPoint(lookRot * PointB));
         Gizmos.DrawLine(transform.TransformPoint(lookRot * PointB), transform.TransformPoint(lookRot * PointC));
         Gizmos.DrawLine(transform.TransformPoint(lookRot * PointC),  transform.TransformPoint(lookRot * PointD));
         Gizmos.DrawLine(transform.TransformPoint(lookRot * PointD), transform.TransformPoint(lookRot * PointA));
         
         //Draw Circle
         Gizmos.color = Color.green;
         int sides = 32;
         Vector3 RadiusVector = new Vector3(0f, Radius, 0f);
         for(int i=0;i<sides;i++){
             
             Quaternion     rotationA = Quaternion.Euler(0f, 0f, (360f/sides)*i),
                         rotationB = Quaternion.Euler(0f, 0f, (360f/sides)*(i+1));//get points for the side we're on
             
             PointA = rotationA * RadiusVector;
             PointB = rotationB * RadiusVector;//scale points by the size of the ring
             
             PointA = transform.TransformPoint(lookRot * PointA);
             PointB = transform.TransformPoint(lookRot * PointB);//rotate the ring towards the camera
             
             Gizmos.DrawLine(PointA, PointB);
         }
     }
 }


The editor script

 using UnityEngine;
 using UnityEditor;
 using System.Collections;
 
 [CanEditMultipleObjects, CustomEditor( typeof(TestData))]
 public class ACTestEditor : Editor {
     
     private static Vector3 pointSnap = Vector3.one * 0.1f;
     
     private SerializedObject test;
     private SerializedProperty
         innerRect,
         outerRect,
         Radius;
     
     void OnEnable(){
         
         test           = new SerializedObject(targets);
         innerRect      = test.FindProperty("innerRect");
         outerRect      = test.FindProperty("outerRect");
         Radius          = test.FindProperty("Radius");
     }
     
     public override void OnInspectorGUI ()
     {
         foreach(TestData t in targets){
                 t.GetTestData();
         }
         test.Update();
         
         
         EditorGUILayout.BeginHorizontal();
         {
             EditorGUILayout.PropertyField(innerRect, true);
             EditorGUILayout.PropertyField(outerRect, true);
         }
         EditorGUILayout.EndHorizontal();
         EditorGUILayout.BeginHorizontal();
         {
             EditorGUILayout.PropertyField(Radius);
         }
         EditorGUILayout.EndHorizontal();
         
         if(test.ApplyModifiedProperties() ||    (Event.current.type == EventType.ValidateCommand &&    Event.current.commandName == "UndoRedoPerformed")){
             foreach(TestData t in targets){
                 t.UpdateTestData();
             }
         }
     }
     
     void OnSceneGUI(){
         //Custom Handles
         TestData test = (TestData)target;
         test.GetTestData();
         Transform tTransform = test.transform;
         Undo.SetSnapshotTarget(test, "Adjust Test Data");
         
         //Camera angle
         Vector3 CamRot = Camera.main.transform.forward;
         Quaternion lookRot = Quaternion.LookRotation(CamRot);
         
         
         //inner box
         Handles.color = Color.red;
         Vector3 innerRectWidth  = new Vector3(test.innerRect.x/2, 0, 0),
                 innerRectHeight = new Vector3(0, test.innerRect.y/2, 0);
         
         for(int i=0; i<4; i++){
 
             Vector3 handlePoint;
             
             switch(i){
                 case 0:
                     handlePoint = innerRectHeight - innerRectWidth/2;
                     break;
                 case 1:
                     handlePoint = innerRectWidth + innerRectHeight/2;
                     break;
                 case 2:
                     handlePoint = -innerRectHeight + innerRectWidth/2;
                     break;
                 case 3:
                     handlePoint = -innerRectWidth - innerRectHeight/2;
                     break;
                 default:
                     handlePoint = Vector3.zero;
                     break;
             }
             
             handlePoint = tTransform.TransformPoint(lookRot * handlePoint);
             
             Vector3    newPoint = Handles.FreeMoveHandle(handlePoint, Quaternion.identity, HandleUtility.GetHandleSize(handlePoint)/5, pointSnap, Handles.SphereCap);
             
             if(handlePoint != newPoint){
                 newPoint = newPoint - tTransform.position;
                 newPoint = Quaternion.Inverse(lookRot) * newPoint;
                 
                 switch(i){
                     case 0:
                         test.innerRect.y = newPoint.y*2;
                         break;
                     case 1:
                         test.innerRect.x = newPoint.x*2;
                         break;
                     case 2:
                         test.innerRect.y = -newPoint.y*2;
                         break;
                     case 3:
                         test.innerRect.x = -newPoint.x*2;
                         break;
                     default:
                         break;
                 }
                 test.UpdateTestData();
             }
         }
         
         //outer box
         Handles.color = Color.yellow;
         Vector3 outerRectWidth  = new Vector3(test.outerRect.x/2, 0, 0),
                 outerRectHeight = new Vector3(0, test.outerRect.y/2, 0);
         
         for(int i=0; i<4; i++){
 
             Vector3 handlePoint;
             
             switch(i){
                 case 0:            
                     handlePoint = outerRectHeight + outerRectWidth/2;
                     break;
                 case 1:
                     handlePoint = outerRectWidth - outerRectHeight/2;
                     break;
                 case 2:
                     handlePoint = -outerRectHeight - outerRectWidth/2;
                     break;
                 case 3:
                     handlePoint = -outerRectWidth + outerRectHeight/2;
                     break;
                 default:
                     handlePoint = Vector3.zero;
                     break;
             }
             
             handlePoint = tTransform.TransformPoint(lookRot * handlePoint);
                 
             Vector3    newPoint = Handles.FreeMoveHandle(handlePoint, Quaternion.identity, HandleUtility.GetHandleSize(handlePoint)/5, pointSnap, Handles.SphereCap);
                 
             if(handlePoint != newPoint){
                 newPoint = newPoint - tTransform.position;
                 newPoint = Quaternion.Inverse(lookRot) * newPoint;
                     
                 switch(i){
                     case 0:
                         test.outerRect = new Vector2(test.outerRect.x, newPoint.y*2);
                         break;
                     case 1:
                         test.outerRect = new Vector2(newPoint.x*2, test.outerRect.y);
                         break;
                     case 2:
                         test.outerRect = new Vector2(test.outerRect.x, -newPoint.y*2);
                         break;
                     case 3:
                         test.outerRect = new Vector2(-newPoint.x*2, test.outerRect.y);
                         break;
                     default:
                         break;
                 }
                 test.UpdateTestData();
             }
         }
         
         
         //radius
         Handles.color = Color.green;
         Vector3 RadiusVector = new Vector3(0f, test.Radius, 0f);
         for(int i = 0; i < 4; i++){
             Quaternion rotation = Quaternion.Euler(0f, 0f, 90f*i);
             Vector3    oldPoint = rotation * RadiusVector;
                 
             oldPoint = tTransform.TransformPoint(lookRot * oldPoint);
                 
             Vector3 newPoint = Handles.FreeMoveHandle(oldPoint, Quaternion.identity, HandleUtility.GetHandleSize(oldPoint)/5, pointSnap, Handles.SphereCap);
             
             if(oldPoint != newPoint){
                 test.Radius = Vector3.Magnitude(newPoint - tTransform.position);
                 test.UpdateTestData();
             }
         }
     }
 }


An example:

I've created an isolated package of the problem in hopes that it might make my issue clearer to others. https://dl.dropbox.com/u/1672880/test%20bug%20package.unitypackage

  • Simply add the package to an empty project, drag the test object into the scene and modify its shape using the handles.

  • (If you see wireframes of the collider components over the gizmos, just collapse the components in the inspector)

  • Make sure the object is deselected and then press play. You'll see the gizmos reset to their original shape and size.

  • If you go back to edit mode and reselect the object, you should see the gizmos update to their proper settings.

  • Additionally, if you now edit the shapes from the custom inspector, those settings will be remembered at runtime.

My current suspicions are that it is something to do with serialization, which I admit I know very little about, so any help or push in the right direction would be greatly appreciated, thankyou.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by whydoidoit · Mar 16, 2013 at 08:34 PM

A long question, but a short answer!

You need to put an EditorUtility.SetDirty(test); after each test.UpdateTestData() to tell the system that you've modified something and it needs saving.

If you cross post on the forum please include a link to the other post in each direction.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image CoatsinkPC · Mar 16, 2013 at 09:12 PM 0
Share

That did it! Thank you very much! I'll make sure to update the forum thread with the answer and a link to here.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

11 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to assign a class ID at runtime? 0 Answers

How to move value in the inspector to script in the assetbundle 0 Answers

How to control serialized variables over the inspector pane? 1 Answer

How to Serialize Scriptable Object at Runtime? 1 Answer

How to control the exposure of public variables in the inspector pane based on a value of another variable? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges