Forum rules - please read before posting.

Change order in layer to a new number

edited May 2021 in Technical Q&A

Hi there,
Any action that allows changing the "Order in layer" for a non-character game object (and also any remember component to remember this)?

Thanks

Comments

  • You can control such a property through animation, play it back with the Object: Animate Action, and store its state with the Remember Animator component.

  • edited May 2021

    Oh, do you mean by also creating an animation then? I was thinking of something more along the lines of the "Character:Change rendering".
    Since this isn't all that uncommon and I don't really want to animate anything, it might be worth adding a dedicated action for it?

    Either way, thank you for the anim solution though - would've never thought of doing it that way :)

  • edited May 2021

    Edit: sorry, I thought I had a similar script, but I don't.

  • edited July 2022

    it might be worth adding a dedicated action for it?

    Custom Actions can be plugged in to extend AC whenever necessary - here's a sample one that changes the order of a supplied Renderer.

    Name the file ActionSortingOrder.cs, place it in a dedicated folder, and point to it in the Actions Manager. It'll then be available as Object: Change sorting order.

    using UnityEngine;
    
    namespace AC
    {
    
        [System.Serializable]
        public class ActionSortingOrder : Action
        {
    
            public Renderer renderer;
            public int newSortingOrder;
    
            public override ActionCategory Category { get { return ActionCategory.Object; }}
            public override string Title { get { return "Change sorting order"; }}
    
            public override float Run ()
            {
                renderer.sortingOrder = newSortingOrder;
                return 0f;
            }
    
            public override void Skip ()
            {
                 Run ();
            }
    
            #if UNITY_EDITOR
    
            public override void ShowGUI ()
            {
                renderer = (Renderer) UnityEditor.EditorGUILayout.ObjectField ("Renderer:", renderer, typeof (Renderer), true);
                newSortingOrder = UnityEditor.EditorGUILayout.IntField ("New sorting order:", newSortingOrder);
            }
    
            #endif
    
        }
    
    }
    
  • Thanks for the action. Changing the sorting order in runtime isn't so much the problem as having it saved though, why I figured it might be worth to pair it with a Remember component in AC.

  • Custom Remember components are possible, too - see this tutorial.

    Though, with the animation workflow, and use of the Remember Animator component, no scripting is necessary.

  • Ah, cool - I'll write a RememberSorting component then. Thanks for the pointers!

  • I'd love to use this script but I'm getting a console error. I've put the script in a folder called Custom Actions, where my other custom actions live.

    Suggestions as to what I'm doing wrong?

    (My AC v 1.75.4, Unity 2020.3.20f1)

    ActionSortingOrder.cs(16,31): error CS0161: 'ActionSortingOrder.Run()': not all code paths return a value

    ActionSortingOrder.cs(30,76): error CS1503: Argument 1: cannot convert from 'string' to 'UnityEngine.Object'

    ActionSortingOrder.cs(30,89): error CS1503: Argument 2: cannot convert from 'UnityEngine.Renderer' to 'System.Type'

  • It was a typo on my part. Try the updated script above.

  • I used this script in my game and it works great. I'm trying to extend it a bit to make it accept an AL parameter. I think I'm almost there and when I launch the AL directly it works great, accepting the default value of the parameter.

    The problem is that when I launch the AL from another AL, assigning the parameter (or even without assigning it and using the default values), I get this error:

    UnassignedReferenceException: The variable objectToAffect of ChangeSortingOrder has not been assigned.
    You probably need to assign the objectToAffect variable of the ChangeSortingOrder script in the inspector.

    I found this particularly weird since the action works by itself

    My edits are mainly taken from the script tutorial 2/3. here's my script:

    public GameObject objectToAffect;
        public Renderer renderer;
                protected SortingGroup sortingGroup;
        public int newSortingOrder;
                public int parameterID = -1;
                private int constantID;
    
        public override ActionCategory Category { get { return ActionCategory.Custom; }}
        public override string Title { get { return "Change sorting order"; }}
    
    
        public override float Run ()
        {
                    renderer = objectToAffect.GetComponent<Renderer>();
                    sortingGroup = renderer.GetComponent<SortingGroup>();
                    if (sortingGroup)
                    {
                        sortingGroup.sortingOrder = newSortingOrder;
                    }
                    renderer.sortingOrder = newSortingOrder;
          return 0f;
        }
    
        public override void Skip ()
        {
             Run ();
        }
    
        #if UNITY_EDITOR
    
        public override void ShowGUI (List<ActionParameter> parameters)
        {
                    parameterID = Action.ChooseParameterGUI("GameObject to affect:", parameters, parameterID, ParameterType.GameObject);
                    if (parameterID >= 0)
                    {
                        constantID = 0;
                        objectToAffect = null;
                    }
                    else
                    {
                        objectToAffect = (GameObject) EditorGUILayout.ObjectField("GameObject to affect:", objectToAffect, typeof (GameObject), true);
                        constantID = FieldToID (objectToAffect, constantID);
                        objectToAffect = IDToField (objectToAffect, constantID, true);
                    }
    
                    newSortingOrder = UnityEditor.EditorGUILayout.IntField ("New sorting order:", newSortingOrder);
        }
    
                override public void AssignValues (List<ActionParameter> parameters)
                {
                    objectToAffect = AssignFile (parameters, parameterID, constantID, objectToAffect);
                }
    
        #endif
    
  • Your AssignValues function needs to be outside of the UNITY_EDITOR directive.

  • Thanks, but unfortunately that wasn't it. I'm still getting the same error. Here's the actual .cs file for good measure

  • Not sure if related, but I also noticed that when clicking on the little button besides the action parameters that brings up the assets list, I get this other error (the button works fine though)

    GUI Error: Invalid GUILayout state in ActionListEditorWindow view. Verify that all layout Begin/End calls match
    UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

  • My bad, the error was in the AL, not the script :( I had forgot one additional instance of the action that had lost the target when I refactored the script, and it was that one that was blocking the whole thing. The script works as it is!

    I still get the console error of my last message, but it's not blocking and doesn't impact any aspect of the action apparently.

  • @kloot Could you please share me the RememberSorting script? I really need it and I can't write one by myself, thank you so much! :)

  • Hey @Lawfish, here's the RememberSorting script I used for this:

    using UnityEngine;
    
    namespace AC
    {
        [RequireComponent(typeof(SpriteRenderer))]
        public class RememberSorting : Remember
        {
            public int previousSortingOrder;
    
            public override string SaveData()
            {
                var renderer = GetComponent<SpriteRenderer>();
    
                var data = new SortingData();
                data.sortingOrder = renderer.sortingOrder;
                data.previousSortingOrder = previousSortingOrder;
                data.objectID = constantID;
    
                return Serializer.SaveScriptData<SortingData>(data);
            }
    
            public override void LoadData(string stringData)
            {
                var data = Serializer.LoadScriptData<SortingData>(stringData);
                if (data == null)
                    return;
    
                var renderer = GetComponent<SpriteRenderer>();
                renderer.sortingOrder = data.sortingOrder;
                previousSortingOrder = data.previousSortingOrder;
            }
        }
    
        [System.Serializable]
        public class SortingData : RememberData
        {
            public int previousSortingOrder;
            public int sortingOrder;
            public SortingData() { }
        }
    }
    
  • Thank you so much! :D

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.