Skip to content

Instantly share code, notes, and snippets.

@cjacobwade
Created February 19, 2022 01:55
Show Gist options
  • Save cjacobwade/37bc152627d6afa58bf2301e1b126cab to your computer and use it in GitHub Desktop.
Save cjacobwade/37bc152627d6afa58bf2301e1b126cab to your computer and use it in GitHub Desktop.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
[ExecuteInEditMode]
[ImageEffectAllowedInSceneView]
public class WalkableCollisionEffect : MonoBehaviour
{
private readonly string normalShaderName = "Big Hops/Walkable Collision Normal";
[SerializeField]
private PlayerMotor playerPrefab = null;
[SerializeField]
private Color goodColor = Color.green;
[SerializeField]
private Color midColor = Color.yellow;
[SerializeField]
private Color badColor = Color.red;
[SerializeField]
private Texture2D convexTex = null;
private Dictionary<PrimitiveType, string> primitiveToResourceStringMap = new Dictionary<PrimitiveType, string>()
{
{ PrimitiveType.Cube, "Cube.fbx"},
{ PrimitiveType.Sphere, "New-Sphere.fbx"},
{ PrimitiveType.Capsule, "New-Capsule.fbx" }
};
private CommandBuffer cmd = null;
private CommandBuffer CMD
{
get
{
if (cmd == null)
{
cmd = new CommandBuffer();
cmd.name = "WalkableCollisionEffect";
}
return cmd;
}
}
private Material normalMat = null;
private MaterialPropertyBlock propertyBlock = null;
public MaterialPropertyBlock PropertyBlock
{
get
{
if (propertyBlock == null)
propertyBlock = new MaterialPropertyBlock();
return propertyBlock;
}
}
private void Awake()
{
if (!Debug.isDebugBuild)
{
enabled = false;
Destroy(this);
return;
}
enabled = BigHopsPrefs.Instance.VisualizeCollision;
}
private void OnEnable()
{
Camera camera = GetComponent<Camera>();
if (camera != null)
{
foreach (var existingCMD in camera.GetCommandBuffers(CameraEvent.BeforeImageEffects))
{
if (existingCMD.name == CMD.name)
return;
}
camera.AddCommandBuffer(CameraEvent.BeforeImageEffects, CMD);
UpdateColliderCommands();
}
}
private void Update()
{
UpdateColliderCommands();
}
private void OnDisable()
{
Camera camera = GetComponent<Camera>();
if (camera != null)
camera.RemoveCommandBuffer(CameraEvent.BeforeImageEffects, CMD);
}
private void UpdateColliderCommands()
{
CMD.Clear();
List<Collider> allColliders = new List<Collider>();
var allLoadedColliders = FindObjectsOfType<Collider>(true);
foreach(var collider in allLoadedColliders)
{
if( collider.enabled && !collider.isTrigger &&
collider.gameObject.activeInHierarchy &&
collider.gameObject.scene.IsValid())
{
allColliders.Add(collider);
}
}
if (playerPrefab != null)
{
CMD.SetGlobalFloat("_MaxWalkAngle", playerPrefab.MaxGroundCheckAngle);
CMD.SetGlobalVector("_WallAngleRange", new Vector2(playerPrefab.WallCheckAngleRange.min, playerPrefab.WallCheckAngleRange.max));
}
CMD.SetGlobalColor("_GoodColor", goodColor);
CMD.SetGlobalColor("_MidColor", midColor);
CMD.SetGlobalColor("_BadColor", badColor);
CMD.SetGlobalTexture("_ConvexTex", convexTex);
CMD.SetRenderTarget(BuiltinRenderTextureType.CurrentActive);
CMD.SetGlobalTexture("_Depth01", BuiltinRenderTextureType.Depth);
if (normalMat == null)
{
Shader normalShader = Shader.Find(normalShaderName);
normalMat = new Material(normalShader);
}
foreach (var collider in allColliders)
{
Transform colTransform = collider.transform;
Vector3 pos = colTransform.position;
Quaternion rot = colTransform.rotation;
Vector3 scale = colTransform.localScale;
bool isConvex = false;
Mesh mesh = null;
MeshCollider meshCol = collider as MeshCollider;
if(meshCol != null)
{
isConvex = meshCol.convex;
mesh = meshCol.sharedMesh;
//if convex ??
}
else
{
PrimitiveType primitiveType = PrimitiveType.Sphere;
BoxCollider boxCol = collider as BoxCollider;
if(boxCol != null)
{
pos += boxCol.center;
scale.Scale(boxCol.size);
primitiveType = PrimitiveType.Cube;
}
SphereCollider sphereCol = collider as SphereCollider;
if (sphereCol != null)
{
pos += sphereCol.center;
scale *= sphereCol.radius * 2f;
primitiveType = PrimitiveType.Sphere;
}
CapsuleCollider capsuleCol = collider as CapsuleCollider;
if (capsuleCol != null)
{
pos += capsuleCol.center;
float relativeHeight = capsuleCol.height / 2f;
float relativeThickness = capsuleCol.radius / 0.5f;
Vector3 relativeScale = new Vector3(relativeThickness, relativeHeight, relativeThickness);
scale.Scale(relativeScale);
if (capsuleCol.direction == (int)Axis.Z)
rot = Quaternion.AngleAxis(90f, colTransform.right) * rot;
else if (capsuleCol.direction == (int)Axis.X)
rot = Quaternion.AngleAxis(90f, colTransform.forward) * rot;
primitiveType = PrimitiveType.Capsule;
}
mesh = Resources.GetBuiltinResource<Mesh>(primitiveToResourceStringMap[primitiveType]);
}
if (mesh == null)
continue;
Matrix4x4 matrix = Matrix4x4.TRS(pos, rot, scale);
PropertyBlock.SetFloat("_Convex", isConvex ? 1f : 0f);
for(int i =0; i< mesh.subMeshCount; i++)
CMD.DrawMesh(mesh, matrix, normalMat, i, 0, PropertyBlock);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment