Skip to content

Instantly share code, notes, and snippets.

@elringus
Created September 4, 2015 17:37
Show Gist options
  • Save elringus/8533773f99db56f66232 to your computer and use it in GitHub Desktop.
Save elringus/8533773f99db56f66232 to your computer and use it in GitHub Desktop.
PlayerCollisionTester
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
using System.Collections;
using System.Collections.Generic;
public class vgPlayerCollisionTester : vgMonoBehaviour
{
public float checkDistance = 10.0f;
public float checksPerMeter = 5.0f;
public float warningAngleTolerance = 5.0f;
public int checksPerFrame = 500;
private MeshFilter dynamicMesh = null;
public List<Vector3> newVertices = new List<Vector3>();
public List<int> newTriangles = new List<int>();
public List<Vector2> newUV = new List<Vector2>();
private static Vector2 uvRed = new Vector2(0.125f, 1.0f);
private static Vector2 uvGreen = new Vector2(0.625f, 1.0f);
private static Vector2 uvWhite = new Vector2(0.875f, 1.0f);
public GameObject playerObject;
private float maxAngle = 90.0f;
private int checkTracker = 0;
// Use this for initialization
void OnEnable()
{
MeshRenderer renderer = gameObject.GetComponent<MeshRenderer>();
if( renderer == null )
{
renderer = gameObject.AddComponent<MeshRenderer>();
}
dynamicMesh = gameObject.GetComponent<MeshFilter>();
if( dynamicMesh == null )
{
dynamicMesh = gameObject.AddComponent<MeshFilter>();
}
playerObject = transform.parent.gameObject;
transform.ClearLocals();
renderer.material.shader = Shader.Find("Particles/Additive");
renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
Texture debugTexture = Resources.Load<Texture>("DebugTextures/debug_color_rygw_4x4");
renderer.material.mainTexture = debugTexture;
float checkHalfDistance = checkDistance * 0.5f;
Vector3 startCorner = new Vector3( -checkHalfDistance, 0.0f, -1.0f);
float strideDistance = 1.0f / checksPerMeter;
int checkNumber = Mathf.RoundToInt( checkDistance / strideDistance );
Vector3 xVector = new Vector3(strideDistance, 0.0f, 0.0f);
Vector3 zVector = new Vector3(0.0f, 0.0f, strideDistance);
newTriangles.Clear();
newVertices.Clear();
newUV.Clear();
for( int xIndex = 0; xIndex < checkNumber; ++xIndex )
{
for( int zIndex = 0; zIndex < checkNumber; ++zIndex )
{
newVertices.Add( startCorner + (xVector * xIndex) + (zVector * zIndex) );
newUV.Add(uvWhite);
if( xIndex > 0 && zIndex > 0 )
{
int baseIndex = newVertices.Count - 1;
newTriangles.Add(baseIndex);
newTriangles.Add(baseIndex - checkNumber);
newTriangles.Add(baseIndex - 1);
newTriangles.Add(baseIndex - checkNumber);
newTriangles.Add(baseIndex - checkNumber - 1);
newTriangles.Add(baseIndex - 1);
}
}
}
maxAngle = playerObject.GetComponent<CharacterController>().slopeLimit;
}
// Update is called once per frame
void Update ()
{
Mesh mesh = dynamicMesh.mesh;
if( checkTracker >= newVertices.Count )
{
checkTracker = 0;
}
int maxIndexThisFrame = checkTracker + checksPerFrame;
for( int i = checkTracker; i < newVertices.Count && i < maxIndexThisFrame; ++i )
{
++checkTracker;
Vector3 worldPosition = newVertices[i];
worldPosition = gameObject.transform.TransformPoint(worldPosition);
worldPosition.y = playerObject.transform.position.y;
worldPosition += Vector3.up * 1.0f;
RaycastHit hitInfo;
LayerMask playerLayerMask = vgPhysicsManager.GetPhysicsMask(playerObject);
float roofCheckDistance = 2.0f;
float floorCheckDistance = 10.0f;
if( Physics.SphereCast(worldPosition, 0.4f, Vector3.up, out hitInfo, roofCheckDistance, playerLayerMask) )
{
worldPosition = hitInfo.point - (Vector3.up * 0.1f);
floorCheckDistance += hitInfo.distance;
}
else
{
worldPosition += Vector3.up * roofCheckDistance;
floorCheckDistance += roofCheckDistance;
}
if( Physics.SphereCast(worldPosition, 0.4f, Vector3.down, out hitInfo, floorCheckDistance, playerLayerMask) )
{
Vector3 vertPoint = newVertices[i];
vertPoint.y = hitInfo.point.y - gameObject.transform.position.y;
vertPoint.y += playerObject.GetComponent<CharacterController>().radius;
newVertices[i] = vertPoint;
float groundAngle = Vector3.Angle(hitInfo.normal, Vector3.up);
if( hitInfo.collider.gameObject.tag == "Player" || hitInfo.collider.gameObject.tag == "MainCamera" )
{
vertPoint.y = gameObject.transform.localPosition.y;
newVertices[i] = vertPoint;
newUV[i] = uvGreen;
}
else if( groundAngle > maxAngle )
{
newUV[i] = uvRed;
}
else if( maxAngle - groundAngle < warningAngleTolerance )
{
Vector2 currentUV = newUV[i];
currentUV.y = 0.0f;
newUV[i] = currentUV;
}
else
{
newUV[i] = uvGreen;
}
}
else
{
Vector3 vertPoint = newVertices[i];
vertPoint.y = 0.0f;
newVertices[i] = vertPoint;
newUV[i] = uvWhite;
}
}
mesh.Clear();
mesh.vertices = newVertices.ToArray();
mesh.triangles = newTriangles.ToArray();
mesh.uv = newUV.ToArray();
mesh.Optimize();
mesh.RecalculateNormals();
}
#if UNITY_EDITOR
[MenuItem("Window/Video Game/Add Player Collision Tester", false, vgMath.vgWindowPriority)]
public static void Init()
{
if( !Application.isPlaying )
{
return;
}
GameObject playerObject = vgPlayerController.playerGameObject;
if( playerObject != null )
{
GameObject collisionTester = new GameObject( "Collision Tester" );
collisionTester.SetActive(false);
collisionTester.AddComponent<vgPlayerCollisionTester>();
collisionTester.transform.parent = playerObject.transform;
collisionTester.SetActive(true);
}
}
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment