I used thepostin the 'EDIT 2' to come up with a decent solution. I don't know if it will work 100% of the time and I would love for someone to correct me if I have chosen a poor solution. This should allow me to run code before the build starts, and if the build fails or succeeds without changing the unity build pipeline.
class CustomBuildPipeline : MonoBehaviour, IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
public int callbackOrder => 0;
// CALLED BEFORE THE BUILD
public void OnPreprocessBuild(BuildReport report)
{
// Start listening for errors when build starts
Application.logMessageReceived += OnBuildError;
}
// CALLED DURING BUILD TO CHECK FOR ERRORS
private void OnBuildError(string condition, string stacktrace, LogType type)
{
if (type == LogType.Error)
{
// FAILED TO BUILD, STOP LISTENING FOR ERRORS
Application.logMessageReceived -= OnBuildError;
}
}
// CALLED AFTER THE BUILD
public void OnPostprocessBuild(BuildReport report)
{
// IF BUILD FINISHED AND SUCCEEDED, STOP LOOKING FOR ERRORS
Application.logMessageReceived -= OnBuildError;
}
}
With recent Unity versions (2020, 2021 and 2022) Flutter Android builds will take a lot longer, because it also has to compile the IL2CPP code from Unity.
From the Readme:
Android builds takes forever to complete Unity 2022.1.*, remove these lines from unityLibrary/build.gradle filecommandLineArgs.add("--enable-debugger") commandLineArgs.add("--profiler-report") commandLineArgs.add("--profiler-output-file=" + workingDir + "/build/il2cpp_"+ abi + "_" + configuration + "/il2cpp_conv.traceevents")
Here is some testing to check how to speed things up.
Or C#EditorUserBuildSettings.il2CppCodeGeneration = UnityEditor.Build.Il2CppCodeGeneration.OptimizeSize;
C++ compiler configuration
InPlayer settings -> Other settings -> configuration, selectDebug.
Or C#PlayerSettings.SetIl2CppCompilerConfiguration(BuildTargetGroup.Android, Il2CppCompilerConfiguration.Debug);
Disable script debugging
Don't bother setting this in the Unity settings, it will be overridden by the build script. Assets/FlutterUnityIntegration/Editor/build.cs In the functionDoBuildAndroid()remove the line enabling script debugging. playerOptions.options = BuildOptions.AllowDebugging; This is the same as removingcommandLineArgs.add("--enable-debugger")from the build.gradle file after an export.
Measuring results
When you run a Flutter build, there are multiple IL2CPP stages that report their duration, with 2 sections taking far longer than all others. We can compare these build durations when using different settings in Unity.
The exact durations here aren't important, as this will be different of every computer and project setup. This is afterflutter cleanand a fresh Unity export. Any subsequent runs will be faster because of caching.
Flutter build apk, with an export from Unity 2021.3.5f1 inandroid/unityLibraryon Windows 10.
Settingarmv7 durationarm64 duration
example project
2m:04s
2m:03s
1 - Code generation (faster builds)
1m:41s
1m:38s
2 - Compiler configuration (debug)
45s
43s
3 - No script debugging
30s
30s
1 + 2
35s
34s
1 + 2 + 3
23s
25s
Conclusion
My advice is to add this to the build script inDoBuildAndroid()for any test or debug builds, remove it for final release builds.
Add objects rendered with this shader to the Transparent queue by adding “Queue”=“Transparent” to the subshader’s Tags list. Add “alpha” to the surface function declaration, after the lighting function declaration, so the line becomes “#pragma surface surf Lambert alpha” Actually set the alpha to something in the surface function, i.e. set o.Alpha = whatever you want. I have done these modifications and used the _ColorTint’s alpha channel in the example. Then the shader becomes this:
Shader "-smn-/GlowingBorder" {
Properties {
_ColorTint("ColorTint", Color) = (1,1,1,1)
_MainTex("Main Texture", 2D) = "white" {}
_BumpMap("Normal Map", 2D) = "bump" {}
_RimColorOuter("Rim Color Outer", Color) = (1,1,1,1)
_RimColorInner("Rim Color Inner", Color) = (1,1,1,1)
_RimPowerOuter("Rim Power Outer", Range(0.0, 7.0)) = 3.0
_RimPowerInner("Rim Power Inner", Range(0.0, 20.0)) = 3.0
}
SubShader {
Tags { "Queue"="Transparent" "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert alpha
struct Input {
float4 color : COLOR;
float2 uv_MainTex;
float2 uv_BumpMap;
float3 viewDir;
};
float4 _ColorTint;
sampler2D _MainTex;
sampler2D _BumpMap;
float4 _RimColorOuter;
float4 _RimColorInner;
float _RimPowerOuter;
float _RimPowerInner;
void surf (Input IN, inout SurfaceOutput o) {
IN.color = _ColorTint;
o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb * IN.color;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
o.Alpha = _ColorTint.a; // For example. Could also be the alpha channel on the interpolated vertex color (IN.color.a), or the one from the texture.
half rimOuter = 1.0 -saturate(dot(normalize(IN.viewDir), o.Normal));
half rimInner = saturate(dot(normalize(IN.viewDir), o.Normal));
o.Emission = (_RimColorOuter.rgb * pow(rimOuter, _RimPowerOuter)) + (_RimColorInner.rgb * pow(rimInner, _RimPowerInner)) ;
}
ENDCG
}
FallBack "Diffuse"
}
유니티 (Unity)에서 멀티 키 딕셔너리 (Multi Key Dictionary)를 사용하는 방법에 대해 검색 결과를 제공해드리겠습니다.
멀티 키 딕셔너리는 두 개 이상의 키로 값을 저장하고 검색할 수 있는 자료구조입니다. 유니티에서는 기본적으로 이러한 기능을 제공하지 않지만, 다음과 같은 방법을 사용하여 멀티 키 딕셔너리를 구현할 수 있습니다:
Tuple을 사용한 멀티 키 딕셔너리 구현: Tuple을 이용하여 여러 키를 하나의 키로 묶고, 해당 키에 대한 값을 딕셔너리에 저장하는 방식입니다. 이렇게 하면 여러 키로 값을 조회하거나 저장할 수 있습니다.
using System;
using System.Collections.Generic;
public class MultiKeyDictionary<TKeyTuple, TValue>
{
private Dictionary<TKeyTuple, TValue> dictionary = new Dictionary<TKeyTuple, TValue>();
public void Add(TKeyTuple keys, TValue value)
{
dictionary[keys] = value;
}
public bool TryGetValue(TKeyTuple keys, out TValue value)
{
return dictionary.TryGetValue(keys, out value);
}
}
// 사용 예시
var multiKeyDict = new MultiKeyDictionary<(int, string), int>();
multiKeyDict.Add((1, "key1"), 100);
multiKeyDict.Add((2, "key2"), 200);
if (multiKeyDict.TryGetValue((1, "key1"), out int result))
{
Debug.Log("Value found: " + result);
}
C# 9의 init-only 프로퍼티와 튜플 사용: C# 9부터 init-only 프로퍼티를 사용하여 딕셔너리의 값을 읽기 전용으로 설정하고, 튜플을 활용하여 멀티 키를 표현할 수 있습니다.
using System;
using System.Collections.Generic;
public class MultiKeyDictionary<TValue>
{
private Dictionary<(int, string), TValue> dictionary = new Dictionary<(int, string), TValue>();
public void Add(int key1, string key2, TValue value)
{
dictionary[(key1, key2)] = value;
}
public IReadOnlyDictionary<(int, string), TValue> Dictionary => dictionary;
}
// 사용 예시
var multiKeyDict = new MultiKeyDictionary<int>();
multiKeyDict.Add(1, "key1", 100);
multiKeyDict.Add(2, "key2", 200);
if (multiKeyDict.Dictionary.TryGetValue((1, "key1"), out int result))
{
Debug.Log("Value found: " + result);
}
이렇게 유니티에서 멀티 키 딕셔너리를 구현할 수 있습니다. 코드는 예시일 뿐이며, 실제 프로젝트에서 적절한 방식으로 적용하셔야 합니다.