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