Unity C# 函数笔记

寻找子对象的某个组件

	public T FindTransform<T>(string name, Transform trans) where T : Component
	{
    	foreach (T c in trans.GetComponentsInChildren<T>())
    	{
        	if (c.name == name)
        	{
            	return c;
        	}
    	}

    	return null;
	}

获取RenderFeature

	private static readonly Dictionary<ScriptableRenderer, Dictionary<string, ScriptableRendererFeature>> s_renderFeatures = new Dictionary<ScriptableRenderer, Dictionary<string, ScriptableRendererFeature>>();

	public static ScriptableRendererFeature GetRendererFeature(this ScriptableRenderer renderer, string name)
	{
    	if (!s_renderFeatures.TryGetValue(renderer, out var innerFeatures))
    	{
        	var propertyInfo = renderer.GetType().GetProperty("rendererFeatures", BindingFlags.Instance | BindingFlags.NonPublic);
        
        	List<ScriptableRendererFeature> rendererFeatures = (List<ScriptableRendererFeature>)propertyInfo?.GetValue(renderer);
        
        	if (rendererFeatures == null)
        	{
            	s_renderFeatures[renderer] = null;
        	}
        	else
        	{
            	innerFeatures = new Dictionary<string, ScriptableRendererFeature>();
            	for (var i = 0; i < rendererFeatures.Count; i++)
            	{
                	var feature = rendererFeatures[i];
                	innerFeatures[feature.name] = feature;
            	}
            	s_renderFeatures[renderer] = innerFeatures;
        	}
    	}
        
    	if (innerFeatures != null)
    	{
        	innerFeatures.TryGetValue(name, out var result);
        	return result;
    	}
        
    	return null;
	}

获取继承某个父类的所有子类类型

	TypeCache.TypeCollection types = TypeCache.GetTypesDerivedFrom<ScriptableRendererFeature>();
	foreach (Type type in types)
	{
    	Debug.Log(type);
	}

OnValidate详解

	/// Timeline 不会触发 OnValidate()

查找对象的根对象

	private Transform GetRoot()
	{
    	var p = this.transform;
    	while (p.parent is {})
    	{
        	p = p.parent;
    	}

    	return p;
	}

	private Transform GetRootByComponent<T>() where T : Component
	{
    	var comp = transform.parent.GetComponentInParent<T>();
    	return comp.transform;
	}

获取材质的所有属性

	private void GetPropertiesInMaterial(Material mat)
	{
    	var len = mat.shader.GetPropertyCount();
    	for (int i = 0; i < len; i++)
    	{
        	var propertyName = mat.shader.GetPropertyName(i);
        	var id              = mat.shader.GetPropertyNameId(i);
        	var desc         = mat.shader.GetPropertyDescription(i);
        	var type               = mat.shader.GetPropertyType(i);
        
        
    	}
	}

Editor事件


private bool LeftClickDown()
{
    if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
        return true;

    return false;
}
    
private bool LeftClickUp()
{
    if (Event.current.type == EventType.MouseUp && Event.current.button == 0)
        return true;

    return false;
}

	private bool LeftDrag()
	{
    	if (Event.current.type == EventType.MouseDrag && Event.current.button == 0)
        	return true;

    	return false;
	}
    
	private bool RightClickDown()
	{
    	if (Event.current.type == EventType.ContextClick)
        	return true;

    	return false;
	}

	private bool BackSpace()
	{
    	if (Event.current.keyCode == KeyCode.Backspace && Event.current.type == EventType.KeyDown)
        	return true;

    	return false;
	}

	private bool ClickInRect(Rect targetRect)
	{
    	return targetRect.Contains(Event.current.mousePosition);
	}

	private Vector2 MousePosition()
	{
    	return Event.current.mousePosition;
	}

	private float MousePositionX()
	{
    	return MousePosition().x;
	}
    
	private float MousePositionY()
	{
    	return MousePosition().y;
	}

追帧操作

	private void UpdateCurrentIntervalDuration()
	{
    	currentIntervalDuration += Time.deltaTime;
    	while (currentIntervalDuration >= m_FrameIntervalTime)
    	{
        	var interval = currentIntervalDuration - m_FrameIntervalTime;

        	m_CurrentIndex++;
        
        	currentIntervalDuration = interval;
    	}
	}

获取资产路径

	AssetDatabase.GetAllAssetPaths()

单例

	public abstract class GameObjectSingleton<T> where T : new()
    {
        public static T Singleton
        {
            get
            {
                if (_singleton == null)
                {
                    if (_singleton == null)
                    {
                        _singleton = new T();
                    }
                }

                return _singleton;
            }

            set { _singleton = value; }
        } 
        private static T _singleton;
    }

    public abstract class GameObjectSynchronousSingleton<T> where T : new()
    {
        private static T _singleton;
        private static object mutex = new object();

        public static T Singleton
        {
            get
            {
                if (_singleton == null)
                {
                    lock (mutex)
                    {
                        if (_singleton == null)
                        {
                            _singleton = new T();
                        }
                    }
                }

                return _singleton;
            }
        } 
    }

    public abstract class UnitySingleton<T> : MonoBehaviour where T : Component
    {
        private static T _singleton = null;

        public static T Singleton
        {
            get
            {
                if (_singleton == null)
                {
                    _singleton = FindObjectOfType(typeof(T)) as T;
                    if (_singleton == null)
                    {
                        UnityEngine.GameObject obj = new UnityEngine.GameObject();
                        _singleton = (T)obj.AddComponent(typeof(T));
                        obj.hideFlags = HideFlags.DontSave;
                        obj.name = typeof(T).Name;
                    }
                }

                return _singleton;
            }
        }

        public virtual void Awake()
        {
            DontDestroyOnLoad(this.gameObject);
            if (_singleton == null)
            {
                _singleton = this as T;
            }
            else
            {
                Destroy(this.gameObject);
            }
        }
    }

计时器

	public class Timer
    {
        public enum STATE
        {
            Idle,
            Run,
            Finished
        }

        public STATE state = STATE.Idle;
        private float _duration = 1.0f;
        private float _elapsedTime = 0;

        public Timer(float duration = 1)
        {
            this._duration = duration;
        }

        public void UpdateTimer(float deltaTime)
        {
            if (state == STATE.Run)
            {
                _elapsedTime += deltaTime;
                if (_elapsedTime >= _duration)
                    state = STATE.Finished;
            }
        }

        public void Go()
        {
            _elapsedTime = 0;
            state = STATE.Run;
        }

        public void Reset()
        {
            _elapsedTime = 0;
            state = STATE.Idle;
        }

        public void SetDuration(float duration)
        {
            this._duration = duration;
        }

行为按钮

	public class ActionButton
    {
        public bool IsPressing = false;
        public bool OnPressed = false;
        public bool OnRelease = false;
        public bool IsExtending = false;
        public bool IsDelaying = false;

        private bool _lastState = false;
        private bool _currentState = false;

        private readonly Timer _extendTimer = new Timer();
        private readonly Timer _delayTimer  = new Timer();
        private readonly float _extendingDuration = 0.5f;
        private readonly float _delayingDuration  = 0.15f;
    
        public ActionButton(float extendingDuration = 0.5f, float delayingDuration = 0.15f){
            this._extendingDuration = extendingDuration;
            this._delayingDuration = delayingDuration;
        }
    
        public void UpdateButton(bool input, float deltaTime)
        {
            _extendTimer.UpdateTimer(deltaTime);
            _delayTimer.UpdateTimer(deltaTime);

            _currentState = input;
            IsPressing = _currentState;

            OnRelease = false;
            OnPressed = false;
            IsExtending = false;
            IsDelaying = false;

            if(_currentState != _lastState)
            {
                if(_currentState == true)
                {
                    OnPressed = true;
                    StartTimer(_delayTimer, _delayingDuration);
                }
                else
                {
                    OnRelease = true;
                    StartTimer(_extendTimer, _extendingDuration);
                }
            }
            _lastState = _currentState;

            if (_delayTimer.state == Timer.STATE.Run)
            {
                IsDelaying = true;
            }
            
            if (_extendTimer.state == Timer.STATE.Run)
            {
                IsExtending = true;
            }
        }

        void StartTimer(Timer timer, float duration)
        {
            timer.SetDuration(duration);
            timer.Go();
        }
    }

正反形映射到球形

private Vector2 Square2CircleMapping(float x, float y)
{
    var circle = new Vector2();
    circle.x = x * Mathf.Sqrt(1.0f - (y * y) * 0.5f);
    circle.y = y * Mathf.Sqrt(1.0f - (x * x) * 0.5f);

    return circle;
}

判断是否在包围盒内


public bool CheckInBox()
{
    var targetPos = _target.position;
    var matrix = transform.worldToLocalMatrix;
            
    var center = _boxCollider.center;
    var size = _boxCollider.size;
            
    targetPos = matrix.MultiplyPoint(targetPos);
            
    if(targetPos.x >= (center.x - 0.5f * size.x) && targetPos.x <= (center.x + 0.5f * size.x))
        if(targetPos.y >= (center.y - 0.5f * size.y) && targetPos.y <= (center.y + 0.5f * size.y))
            if(targetPos.z >= (center.z - 0.5f * size.z) && targetPos.z <= (center.z + 0.5f * size.z))
                return true;
            
    return false;
}

RenderFeature模板

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class RenderFeature : ScriptableRendererFeature
{
    [System.Serializable]
    public class Settings
    {
        public bool IsEnabled = true;
        public RenderPassEvent WhenToInsert = RenderPassEvent.AfterRendering;
        public Material MaterialToBlit;
    }

    public Settings settings = new Settings();

    private RenderTargetHandle renderTextureHandle;
    private RenderPass myRenderPass;

    public override void Create()
    {
        myRenderPass = new RenderPass(
            "OverWater pass",
            settings.WhenToInsert,
            settings.MaterialToBlit
        );
    }
    
    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        if (!settings.IsEnabled)
        {
            return;
        }

        var cameraColorTargetIdent = renderer.cameraColorTarget;
        myRenderPass.Setup(cameraColorTargetIdent);

        renderer.EnqueuePass(myRenderPass);
    }

    public class RenderPass : ScriptableRenderPass
    {
        private string m_ProfilerTag;

        private Material m_MaterialToBlit;
        private RenderTargetIdentifier m_CameraColorTargetIdent;
        private RenderTargetHandle m_Temp;

        public RenderPass(
            string profilerTag,
            RenderPassEvent renderPassEvent, 
            Material material
        )
        {
            this.m_ProfilerTag = profilerTag;
            this.renderPassEvent = renderPassEvent;
            this.m_MaterialToBlit = material;
        }

        public void Setup(RenderTargetIdentifier cameraColorTargetIdent)
        {
            this.m_CameraColorTargetIdent = cameraColorTargetIdent;
        }

        public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
        {
            cmd.GetTemporaryRT(m_Temp.id, cameraTextureDescriptor);
        }

        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
            cmd.Clear();

            cmd.Blit(m_CameraColorTargetIdent, m_Temp.Identifier(), m_MaterialToBlit, 0);
            cmd.Blit(m_Temp.Identifier(), m_CameraColorTargetIdent);

            context.ExecuteCommandBuffer(cmd);

            cmd.Clear();
            CommandBufferPool.Release(cmd);
        }

        public override void FrameCleanup(CommandBuffer cmd)
        {
            cmd.ReleaseTemporaryRT(m_Temp.id);
        }
    }
}

VP矩阵构建

public Matrix4x4 GetViewMatrix()
    {
        var waterPosition = transform.position;
        var cameraPosition = waterPosition + new Vector3(0, CameraHeight, 0);
        var cameraForward = Vector3.down;
        
        var v = Matrix4x4.TRS(cameraPosition, Quaternion.LookRotation(cameraForward, Vector3.up), Vector3.one).inverse; 
        return v;
    }

    public Matrix4x4 GetProjectionMatrix()
    {
        var aabb = GetAABB();
        var p = Matrix4x4.Ortho(aabb.left, aabb.right, aabb.bottom, aabb.top, 0.0f, 300);
        return p;
    }

    private AABB GetAABB()
    {
        var bound = GetComponent<MeshFilter>().sharedMesh.bounds;
        var aabb = new AABB()
        {
            top = bound.max.z,
            bottom = bound.min.z,
            left = bound.min.x,
            right = bound.max.x
        };

        return aabb;
    }

打包变体过滤

public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> data)
    {
        for (int i = data.Count - 1; i >= 0; --i)
        {
            if (data[i].shaderKeywordSet.IsEnabled(new ShaderKeyword("")))
                data.Remove(data[i]);
        }
    }

Editor ToggleButton

private void ShowToggleButton(ref bool open, string closeStr, string openStr)
{
    string content;
    if (open)
        content = closeStr;
    else
        content = openStr;
    
    if (GUILayout.Button(content))
    {
        open = !open;
    }
}

private void ShowToggleButton(ref bool open, string closeStr, string openStr, Rect rect)
{
    var content = "";
    if (openShaderPerformancePipeline)
        content = closeStr;
    else
        content = openStr;
    if (GUI.Button(rect, content))
    {
        openShaderPerformancePipeline = !openShaderPerformancePipeline;
    }
}

private void ShowToggleButton(ref bool open, string closeStr, string openStr, Rect rect, UnityAction action = null)
    {
        var content = "";
        if (m_OpenShaderPerformancePipeline)
            content = closeStr;
        else
            content = openStr;
        if (GUI.Button(rect, content))
        {
            m_OpenShaderPerformancePipeline = !m_OpenShaderPerformancePipeline;
            action?.Invoke();
        }
    }

RGBM编码

private void EncodeRGBMColor(Color originalColor, out Color rgbmColor, out float rgbmAlpha)
{
    rgbmAlpha = Mathf.Max(Mathf.Max(originalColor.r, originalColor.g), originalColor.b);
    rgbmAlpha = Mathf.Ceil(rgbmAlpha);
        
    rgbmColor = new Color(
        originalColor.r / rgbmAlpha,
        originalColor.g / rgbmAlpha,
        originalColor.b / rgbmAlpha,
        0
    );
}

导出terrain高度图

public void ExportHeightMap()
    {
        var res = terrainData.heightmapResolution;
        var heightMap = new Texture2D(res, res, TextureFormat.R16, false);

        for (int i = 0; i < res; i++)
        {
            for (int j = 0; j < res; j++)
            {
                var u = i / (float)res;
                var v = j / (float)res;
                var height = terrainData.GetInterpolatedHeight(u, v);
                heightMap.SetPixel(i, j, new Color(height, 0,0,0));
            }
        }
        
        heightMap.Apply();

        SaveTexture2Local(heightMap);
    }    
    
    public void SaveTexture2Local(Texture2D tex)
    {       
        Byte[] bytes = tex.EncodeToPNG();
        var path = EditorUtility.SaveFilePanel("ExportPath", Application.streamingAssetsPath, "Terrain", "png");
        File.WriteAllBytes(path, bytes);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值