How to listen for Auto Save events after Prefab modification in Editor

Posted by felixtgomezjr on Thu, 18 Jun 2020 09:06:01 +0200

1) How to listen for Auto Save events after Prefab modification in Editor
2) On the advantages of turning on the Optimal option of animation files
3) Is it helpful for performance to split a large terrain into multiple mesh Colliders
4) Camera.SetReplacementShader And Projector display problems
5) FMOD can't switch sound when plugging in and out headphones on Android



This is the 207th push of UWA technology knowledge sharing. Today, we continue to select a number of development and optimization related issues for you. It is recommended that you read for 10 minutes, and you will get something after reading carefully.

UWA Q & a community: answer.uwa4d.com
UWA QQ group 2: 793972859 (the original group is full)

Editor

Q: As shown in the figure, Auto Save is added to the new Prefab mechanism, and no listening method is found.

The original application can be monitored, but if Auto Save is checked, you don't need to click Apply, so you won't be able to monitor. Can Auto Save be monitored?

 

A: The PrefabStage class is responsible for managing the editing operations of Prefab, and provides a wealth of callbacks PrefabStage source code You can easily monitor each stage:

#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using UnityEditor.Experimental.SceneManagement;

[InitializeOnLoad]
public static class PrefabStageListener
{
    static PrefabStageListener()
    {
        // Open Prefab editing interface callback
        PrefabStage.prefabStageOpened += OnPrefabStageOpened;
        // Callback before Prefab is saved
        PrefabStage.prefabSaving += OnPrefabSaving;
        // Callback after Prefab is saved
        PrefabStage.prefabSaved += OnPrefabSaved;
        // Close Prefab editing interface callback
        PrefabStage.prefabStageClosing += OnPrefabStageClosing;
    }

    //....
}
#endif

PS: if you often want to find some editor private field methods, it is recommended to download dnSpy and open it directly UnityEditor.dll Search for keywords. For example, if you want to implement a function of an interface button through code but can't find an API, you can view the methods in the relevant DLL and try to reflect the call.

Thank you Zhang Di @ UWA Q & a community for your answers. Welcome to the community:
https://answer.uwa4d.com/question/5ee0aecaa45e13073a5710ea

Animation

Q: The animation file in the project has the Optimal option enabled. What are the substantive advantages that can be explained? Which part of the project does it work to turn on the Optimal option?

A: The description of this option in Unity's official documents is not clear:
Let Unity decide how to compress, either by keyframe reduction or by using dense format. If enabled, the Inspector displays Animation Compression Errors options.
Only for Generic and Humanoid Animation Type rigs.

Recommended This article For the curve saving method and related options in the Unity animation file, a detailed description is made. In general, Optimal is to let Unity automatically choose the Optimal curve expression, so as to occupy the minimum storage space.

The answer is provided by UWA, welcome to community communication:
https://answer.uwa4d.com/question/5eb905a04d93790618e0ed25

Physics

Q: Excuse me, in your project, is the terrain part of MeshCollider directly used? Is it better to split a large terrain into multiple meshcolliders? I wonder if you have any optimization experience in this field?

A: According to the previous optimization experience, the number of physical contacts (contact object pairs) has a greater impact on the physical overhead. When calculating whether MeshCollider has contact with other objects, it uses AABB bounding box, so it is recommended to split the curved, narrow and long MeshCollider to avoid too large bounding box, resulting in too many contacts. But for the square terrain block, it's not very good to judge whether it needs to be split or what granularity it needs to be split. There are not many documents or experience sharing in this area.

The answer is provided by UWA, welcome to community communication:
https://answer.uwa4d.com/question/5ec4d442979400061e54534a

Rendering

Q: As shown in the figure, I use Camera.SetReplacementShader This method replaces shaders, scene objects and particles in the scene. However, the Projector does not display normally. I don't know that the processing of the Projector is different from that of other shaders (I also wrote a replacement Shader for it, but it has no effect, and I don't know whether it is The replacement is successful, but it is covered.

In order to test, I made a simpler scenario:

With FrameDebug, you can see its rendering information:

After performing the replacement logic:

Accordingly, its rendering information is as follows:

It can be seen that the replacement is successful, but Blend and ZWrite do not correspond. In the original Projector Shader, Blend SRCAP oneminussrcap and ZWrite Off are set the same in the replacement Shader, but in FrameDebug, Blend One Zero and ZWrite On are seen.

I don't know much about this area. I hope you can give me some advice and answer your doubts about what's wrong. Attach my test script (simply copy it in the replacement Projector Shader).

public class ReplaceShader : MonoBehaviour
{
    public Camera Camera;
    public Shader replaceShader;

    bool isOn;

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space)) {
            ToggleEffect();
        }
    }

    void ToggleEffect()
    {
        isOn = !isOn;
        if (isOn)
        {
            Camera.SetReplacementShader(replaceShader, "RenderType");
        }
        else {
            Camera.ResetReplacementShader();
        }

    }
}

Projection Shader:

Shader "Custom/ProjectorFX_CharacterRing"
{
  Properties {
    _MainColor ("Main Color", Color) = (1,1,1,1)
    _ProjectTex ("Shape", 2D) = "" {}
  }

  Subshader {
    Tags {"Queue"="Transparent+1" "RenderType"="Projector" "ProjectorFX"="Normal"}
    Pass {
      ZWrite Off
      AlphaTest Greater 0
      ColorMask RGB
      Blend SrcAlpha OneMinusSrcAlpha
      Offset -1, -1

      CGPROGRAM

      #pragma vertex vert
      #pragma fragment frag
      #pragma multi_compile_fog

      #include "UnityCG.cginc"

      fixed4 _MainColor;      
      fixed4 _MainTex_ST;
      float4x4 unity_Projector;
      sampler2D _ProjectTex;

      struct vInput {
        float4 vertex : POSITION;
      };

      struct vOutput {
        float4 uvMain : TEXCOORD0;
        UNITY_FOG_COORDS(2)
        float4 pos : SV_POSITION;
      };

      vOutput vert (vInput v)
      {
        vOutput o;
        o.pos = UnityObjectToClipPos(v.vertex);
        o.uvMain = mul(unity_Projector, v.vertex);        

        UNITY_TRANSFER_FOG(o,o.pos);
        return o;
      }

      fixed4 frag (vOutput i) : SV_Target
      {
        fixed4 main = tex2Dproj(_ProjectTex, UNITY_PROJ_COORD(i.uvMain));       
        main *= _MainColor;


        UNITY_APPLY_FOG_COLOR(i.fogCoord, main, fixed4(0,0,0,0));

        return main;
      }
      ENDCG
    }
  }
}

Replacement Shader used:

Shader "Unlit/TestRed"
{  
     Subshader {
    Tags {"Queue"="Transparent+1" "RenderType"="Projector"}
    Pass {
      ZWrite Off
      AlphaTest Greater 0
      ColorMask RGB
      Blend SrcAlpha OneMinusSrcAlpha
      Offset -1, -1

      CGPROGRAM

      #pragma vertex vert
      #pragma fragment frag
      #pragma multi_compile_fog

      #include "UnityCG.cginc"

      fixed4 _MainColor;      
      fixed4 _MainTex_ST;
      float4x4 unity_Projector;
      sampler2D _ProjectTex;

      struct vInput {
        float4 vertex : POSITION;
      };

      struct vOutput {
        float4 uvMain : TEXCOORD0;
        UNITY_FOG_COORDS(2)
        float4 pos : SV_POSITION;
      };

      vOutput vert (vInput v)
      {
        vOutput o;
        o.pos = UnityObjectToClipPos(v.vertex);
        o.uvMain = mul(unity_Projector, v.vertex);        

        UNITY_TRANSFER_FOG(o,o.pos);
        return o;
      }

      fixed4 frag (vOutput i) : SV_Target
      {
        fixed4 main = tex2Dproj(_ProjectTex, UNITY_PROJ_COORD(i.uvMain));       
        main *= _MainColor;


        UNITY_APPLY_FOG_COLOR(i.fogCoord, main, fixed4(0,0,0,0));

        return main;
      }
      ENDCG
    }
  }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = fixed4(1,0,0,1);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }

}

A: From the screenshot of the main topic, we can see that when the Replace Shader is not used, Plane renders twice, one is its own Shader, and the other is the Projector Shader. After using Replace Shader, we can see that Plane is only rendered once in FrameDebugger. It should be that the Projector is not effective. Because only the SubShader of Opaque works, what we see in FrameDebugger is "blend one zero, zwrite on". This is normal, but it just runs to the translucent rendering queue. This is not normal. I tried to change the order of the two subshaders in the replacement Shader of the main subject, and then ran to the Opaque rendering queue.

After searching Google, I found that there are two posts in Unity forum that are related to the questions of the subject, This post It is mentioned in that project is not supported when Replace Shader is used in Unity 5.6.4.

This post It is said that because there is a Bug before, the replacement shader will make the objects affected by the Projector render even if the tags do not match, so the Unity Bug fix will not work if the Projector is changed to use the replacement shader.

thank Xuan@UWA The Q & a community has provided answers. Welcome to the community exchange:
https://answer.uwa4d.com/question/5ed7c18e96525d41c9512b2e

Audio

Q: We use FMOD to play music and sound effects. On Android devices, the mobile phone power amplifier BGM is plugged in at this time. The mobile phone is still in the power amplifier, and it can't be switched to the headset for playing. In addition, switching to Bluetooth is the same problem. Has anyone ever met this problem? The Apple device has no problem.

A: At RuntimeManager.cs Change the OutputType of Android platform to FMOD.OUTPUTTYPE.AUDIOTRACK Just fine.

Thank you for the answers provided by Xu lianyimeng @ UWA Q & a community. Welcome to the community for communication:
https://answer.uwa4d.com/question/5ed7730096525d41c9512b1f

Cover image from Internet

Today's sharing is here. Of course, there is no limit to life. In the long development cycle, you may see these questions are just the tip of the iceberg. We have prepared more technical topics on UWA Q & a website for you to explore and share. Welcome those who love progress to join us. Maybe your method can solve other people's urgent needs, and his "stone" can attack your "jade".

Official website: www.uwa4d.com
Official technology blog: blog.uwa4d.com
Official Q & a community: answer.uwa4d.com
UWA School: edu.uwa4d.com
Official technology QQ group: 793972859 (the original group is full)



Topics: Unity Android Fragment Mobile