寻找子对象的某个组件
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详解
查找对象的根对象
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();
}
}