Created
February 19, 2022 01:55
-
-
Save cjacobwade/37bc152627d6afa58bf2301e1b126cab to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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