Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more..
    Dismiss Notice
  3. Dismiss Notice

Question Saving the rest state of physics Simulation (To a new scene?)

Discussion in 'Scripting' started by Napivo, Sep 28, 2020.

  1. Napivo

    Napivo

    Joined:
    Feb 9, 2015
    Posts:
    39
    I got bored and started to play around with physics2d.

    But I'd like to be able to save starting from my initial level design to a new scene once everything is stabilized.

    So I started out like this

    Start.png

    and would like to save my scene (preferable in a new scene file) like this

    Result.png


    so I can build on the result and build further on stable levels?

    Is there a way to do this.
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,723
    I would probably make a script that waits 5 seconds (or however long it takes to stabilize), then prints the transform data of the relevant objects out to a file. Then load that data back into the scene with an editor script.
     
    Joe-Censored likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,769
    I have never used this API, but I think you can take Praetor's great idea above and collapse it down into one single frame by calling this function:

    https://docs.unity3d.com/ScriptReference/Physics2D.Simulate.html

    You could stick one of those in during a Start() function and I think it will "pump" all your physics for however long you tell it to.
     
    Joe-Censored and PraetorBlue like this.
  4. Napivo

    Napivo

    Joined:
    Feb 9, 2015
    Posts:
    39
    I might have gone about this completely the wrong way... instead of trying to save a scene in game mode, I should have simulated the physics in editor mode.

    https://answers.unity.com/questions/158766/physics-in-scene-editor-mode.html

    Unfortunately, for tonight I need to go to bed as I have work tomorrow but I will let you know in the following days how it goes. When I solve this I will let you all know.
     
    PraetorBlue likes this.
  5. Napivo

    Napivo

    Joined:
    Feb 9, 2015
    Posts:
    39
    As I have promised I would post, when I had a descend answer

    It is an adaptation of https://gist.github.com/gekidoslair/aa9f9685b3ff4077c3209976635ecce8 for 2D Physics.

    What It does:
    - It creates a UI window with a button "start" and "stop".
    - Runs the animation for 10 secs in the editor
    - Can be interrupted

    Things it doesn't do, (possible extensions for me)

    - Freeze objects before start
    - Stop objects from being updated anymore
    - Exclude objects from activating even when hit.
    - Anything else where you want to interfere.

    Any questions can be sent to napivo@gmail.com or posted here
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System.Linq;
    4. using UnityEngine.UIElements;
    5. using System;
    6.  
    7. // This causes the class' static constructor to be called on load and on starting playmode
    8. [InitializeOnLoad]
    9. class PhysicsSettler : EditorWindow
    10. {
    11.     private static GUIStyle SLblRed;
    12.     private static GUIStyle SLblBlue;
    13.  
    14.     private static int activeCount = 0;
    15.     private static bool active = false;
    16.     private static float activeTime = 0;
    17.     private static float timeToSettle = 10;
    18.  
    19.     //// the work list of rigid bodies we can find loaded up
    20.     static Rigidbody2D[] workList;
    21.     static Color[] workListOriginalColors;
    22.  
    23.     //// we need to disable auto simulation to manually tick physics
    24.     static bool cachedAutoSimulation;
    25.  
    26.     private void OnGUI()
    27.     {
    28.         if (active)
    29.         {
    30.             if (GUILayout.Button("Stop Physics"))
    31.             {
    32.                 Deactivate();
    33.             }
    34.         }
    35.         else
    36.         {
    37.             if (GUILayout.Button("Run Physics"))
    38.             {
    39.                 Activate();
    40.             }
    41.         }
    42.  
    43.  
    44.         if (active)
    45.         {
    46.             GUILayout.Space(5);
    47.             GUILayout.Label("Working " , SLblBlue);
    48.             GUILayout.Space(2);
    49.             GUILayout.Label("Active Objects : " + activeCount, SLblRed);
    50.             GUILayout.Space(5);
    51.         }
    52.         else
    53.         {
    54.  
    55.             GUILayout.Space(5);
    56.             GUILayout.Label("Stopped ", SLblBlue);
    57.             GUILayout.Space(2);
    58.             GUILayout.Label("Active Objects : " + activeCount, SLblRed);
    59.             GUILayout.Space(5);
    60.         }
    61.     }
    62.  
    63.     void Deactivate()
    64.     {
    65.         active = false;
    66.         int count = 0;
    67.         foreach (Rigidbody2D body in workList)
    68.         {
    69.             body.gameObject.GetComponent<SpriteRenderer>().color = workListOriginalColors[count];
    70.             count++;
    71.         }
    72.  
    73.         // !!!Extremely needed!!!
    74.         // If not executed will stop Physics in game mode
    75.  
    76.         Physics2D.autoSimulation = true;
    77.     }
    78.  
    79.     void Activate()
    80.     {
    81.         SLblRed = new GUIStyle(EditorStyles.label);
    82.         SLblRed.normal.textColor = Color.red;
    83.  
    84.         SLblBlue = new GUIStyle(EditorStyles.label);
    85.         SLblBlue.normal.textColor = Color.blue;
    86.  
    87.  
    88.         if (!active)
    89.         {
    90.             active = true;
    91.  
    92.             // Normally avoid Find functions, but this is editor time and only happens once
    93.             workList = GameObject.FindObjectsOfType<Rigidbody2D>();
    94.             workListOriginalColors = new Color[workList.Count()];
    95.  
    96.             // we will need to ensure autoSimulation is off to manually tick physics
    97.             cachedAutoSimulation = Physics.autoSimulation;
    98.             activeTime = 0f;
    99.  
    100.             Debug.Log("Bodies found = " + workList.Count());
    101.  
    102.             int count = 0;
    103.             // make sure that all rigidbodies are awake so they will actively settle against changed geometry.
    104.             foreach (Rigidbody2D body in workList)
    105.             {
    106.                 workListOriginalColors[count] = body.gameObject.GetComponent<SpriteRenderer>().color;
    107.                 count++;
    108.  
    109.                 if (DoWakeUp(body))
    110.                 {
    111.                     body.Sleep();
    112.                 }
    113.                 else
    114.                 {
    115.                     body.WakeUp();
    116.                 }
    117.             }
    118.         }
    119.     }
    120.  
    121.     private static bool DoWakeUp(Rigidbody2D body)
    122.     {
    123.         // you can add code to decide if a body needs to be awake or asleep at start
    124.  
    125.         return body.bodyType == RigidbodyType2D.Kinematic;
    126.     }
    127.  
    128.     void Update()
    129.     {  
    130.         if (active)
    131.         {
    132.             Debug.Log("Update Active");
    133.             activeTime += Time.deltaTime;
    134.             Debug.Log("activeTime = " + activeTime);
    135.            
    136.             // make sure we are not autosimulating
    137.            
    138.             /*
    139.              !!!!!!!!!!!!
    140.              Be carefull Physics2D.autoSimulation = true
    141.              Must be execured or Physics will be diabled in game mode
    142.              !!!!!!!!!!!
    143.             */
    144.  
    145.             Physics2D.autoSimulation = false;
    146.  
    147.             // see if all our
    148.             bool allSleeping = true;
    149.             activeCount = 0;
    150.  
    151.             foreach (Rigidbody2D body in workList)
    152.             {
    153.                 SpriteRenderer sr = body.gameObject.GetComponent<SpriteRenderer>();
    154.                 sr.color = Color.green;
    155.  
    156.                 if ((body != null) && (body.bodyType != RigidbodyType2D.Kinematic))
    157.                 {
    158.                     if (!body.IsSleeping())
    159.                     {
    160.                         allSleeping = false;
    161.                         activeCount++;
    162.                         sr.color = Color.red;
    163.                         //Debug.Log("Body = " + body.gameObject.name);
    164.                     }
    165.                 }
    166.             }
    167.  
    168.             Debug.Log("Active : " + active);
    169.  
    170.             if (allSleeping || activeTime >= timeToSettle)
    171.             {
    172.                 Physics2D.autoSimulation = cachedAutoSimulation;
    173.                 Deactivate();
    174.  
    175.                 if (allSleeping)
    176.                 {
    177.                     Debug.Log("All Alseep ending");
    178.                 }
    179.  
    180.                 if (activeTime >= timeToSettle)
    181.                 {
    182.                     Debug.Log("Active time elapsed ending");
    183.                 }
    184.             }
    185.             else
    186.             {
    187.                 SaveObjectdata();
    188.                 Physics2D.Simulate(Time.fixedDeltaTime);
    189.                 CheckObjectdata();
    190.                 //Physics2D.autoSimulation = true;
    191.             }
    192.         }
    193.     }
    194.  
    195.     private void SaveObjectdata()
    196.     {
    197.         // Will save all data needed to check if object will remain active
    198.  
    199.  
    200.         //throw new NotImplementedException();
    201.     }
    202.  
    203.     private void CheckObjectdata()
    204.     {
    205.         // Will check all data to check if object will remain active or fall asleep.
    206.  
    207.         //throw new NotImplementedException();
    208.     }
    209.  
    210.     [MenuItem("Tools/Scene Physics")]
    211.     private static void OpenWindow()
    212.     {
    213.         GetWindow<PhysicsSettler>(false, "Physics", true);
    214.     }
    215. }
     
    Kurt-Dekker likes this.