void UpdateRayPenetrationOnMove(APCharacterMotor oMotor, APCharacterMotor.CharacterRay2D rayToUpdate, Vector2 newPosWs, direction direction) { // Get characters box in world space if available Transform rayTransform = oMotor.transform; Vector2 newPosLs = rayTransform.InverseTransformPoint(newPosWs); // for now we support boxcollider2d only ! System.Type colliderType = oMotor.GetComponent <Collider2D>().GetType(); if (oMotor.GetComponent <Collider2D>() && (colliderType == typeof(UnityEngine.BoxCollider2D))) { UnityEngine.BoxCollider2D boxCollider = (UnityEngine.BoxCollider2D)oMotor.GetComponent <Collider2D>(); Vector2 centerLs = boxCollider.offset; // compute distance from ray position to collider border float fNewPenetration = 0f; switch (direction) { case direction.left: fNewPenetration = newPosLs.x - (centerLs.x - 0.5f * boxCollider.size.x); break; case direction.right: fNewPenetration = (centerLs.x + 0.5f * boxCollider.size.x) - newPosLs.x; break; case direction.up: fNewPenetration = (centerLs.y + 0.5f * boxCollider.size.y) - newPosLs.y; break; case direction.down: fNewPenetration = newPosLs.y - (centerLs.y - 0.5f * boxCollider.size.y); break; } fNewPenetration = Mathf.Max(0f, fNewPenetration); rayToUpdate.m_penetration = fNewPenetration; // / Mathf.Abs(rayTransform.lossyScale.y); // remove any scale as is it applied at runtime } }
void DrawRays(APCharacterMotor oMotor, APCharacterMotor.CharacterRay2D[] rays, Color color, direction direction) { Transform rayTransform = oMotor.transform; for (int i = 0; i < rays.Length; i++) { APCharacterMotor.CharacterRay2D curRay = rays[i]; Vector3 pointPos = oMotor.GetRayPositionWs(curRay); Handles.color = color; Vector3 newPos = Handles.FreeMoveHandle(pointPos, Quaternion.identity, 0.03f, Vector3.zero, Handles.DotCap); if (newPos != pointPos) { Undo.RecordObject(oMotor, "Move Ray Point"); curRay.m_position = rayTransform.InverseTransformPoint(newPos); UpdateRayPenetrationOnMove(oMotor, curRay, newPos, direction); // mark object as dirty EditorUtility.SetDirty(oMotor); } // Draw ray line Vector3 rayDir = rayTransform.up; float fPenScale = rayTransform.lossyScale.y * oMotor.Scale.y; switch (direction) { case direction.left: rayDir = -rayTransform.right; fPenScale = rayTransform.lossyScale.x * oMotor.Scale.x; break; case direction.right: rayDir = rayTransform.right; fPenScale = rayTransform.lossyScale.x * oMotor.Scale.x; break; case direction.down: rayDir = -rayTransform.up; break; } float fPen = curRay.m_penetration * Mathf.Abs(fPenScale); Handles.DrawLine(pointPos, pointPos + (Vector3)rayDir * (fPen + curRay.m_extraDistance)); Handles.CircleCap(0, pointPos + (Vector3)rayDir * fPen, Quaternion.identity, 0.03f); } }
void RebuildRays() { for (int targetId = 0; targetId < targets.Length; targetId++) { // Get characters box if available APCharacterMotor oMotor = (APCharacterMotor)targets[targetId]; Undo.RecordObject(oMotor, "RebuildRays"); Transform rayTransform = oMotor.transform; // for now we support boxcollider2d only ! System.Type colliderType = oMotor.GetComponent <Collider2D>().GetType(); if (oMotor.GetComponent <Collider2D>() && (colliderType == typeof(UnityEngine.BoxCollider2D))) { UnityEngine.BoxCollider2D boxCollider = (UnityEngine.BoxCollider2D)oMotor.GetComponent <Collider2D>(); // build list of horizontal rays APCharacterMotor.CharacterRay2D[] raysUp = new APCharacterMotor.CharacterRay2D[oMotor.m_autoBuilder.m_rayCountX]; APCharacterMotor.CharacterRay2D[] raysDown = new APCharacterMotor.CharacterRay2D[oMotor.m_autoBuilder.m_rayCountX]; APCharacterMotor.CharacterRay2D[] raysFront = new APCharacterMotor.CharacterRay2D[oMotor.m_autoBuilder.m_rayCountY]; APCharacterMotor.CharacterRay2D[] raysBack = new APCharacterMotor.CharacterRay2D[oMotor.m_autoBuilder.m_rayCountY]; // rays up/down { float boxWidthX = boxCollider.size.x * oMotor.m_autoBuilder.m_rayXBoxScale.x; float boxWidthY = boxCollider.size.y * oMotor.m_autoBuilder.m_rayXBoxScale.y; float fOffsetX = -boxWidthX * 0.5f + boxCollider.offset.x; float fOffsetY = -boxWidthY * 0.5f + boxCollider.offset.y; float fSpaceX = oMotor.m_autoBuilder.m_rayCountX > 1 ? boxWidthX / (oMotor.m_autoBuilder.m_rayCountX - 1) : 0f; for (int i = 0; i < oMotor.m_autoBuilder.m_rayCountX; i++) { APCharacterMotor.CharacterRay2D curRayUp = new APCharacterMotor.CharacterRay2D(); curRayUp.m_position.x = fOffsetX + i * fSpaceX; curRayUp.m_position.y = fOffsetY + boxWidthY; curRayUp.m_extraDistance = oMotor.m_autoBuilder.m_extraDistanceUp; UpdateRayPenetrationOnMove(oMotor, curRayUp, rayTransform.TransformPoint(curRayUp.m_position), direction.up); APCharacterMotor.CharacterRay2D curRayDown = new APCharacterMotor.CharacterRay2D(); curRayDown.m_position.x = curRayUp.m_position.x; curRayDown.m_position.y = fOffsetY; curRayDown.m_extraDistance = oMotor.m_autoBuilder.m_extraDistanceDown; UpdateRayPenetrationOnMove(oMotor, curRayDown, rayTransform.TransformPoint(curRayDown.m_position), direction.down); raysUp[i] = curRayUp; raysDown[i] = curRayDown; } } // rays front/back { float boxWidthX = boxCollider.size.x * oMotor.m_autoBuilder.m_rayYBoxScale.x; float boxWidthY = boxCollider.size.y * oMotor.m_autoBuilder.m_rayYBoxScale.y; float fOffsetX = -boxWidthX * 0.5f + boxCollider.offset.x; float fOffsetY = -boxWidthY * 0.5f + boxCollider.offset.y; float fSpaceY = oMotor.m_autoBuilder.m_rayCountY > 1 ? boxWidthY / (oMotor.m_autoBuilder.m_rayCountY - 1) : 0f; for (int i = 0; i < oMotor.m_autoBuilder.m_rayCountY; i++) { APCharacterMotor.CharacterRay2D curRayFront = new APCharacterMotor.CharacterRay2D(); curRayFront.m_position.x = oMotor.m_faceRight ? fOffsetX + boxWidthX : fOffsetX; curRayFront.m_position.y = fOffsetY + i * fSpaceY; curRayFront.m_extraDistance = oMotor.m_autoBuilder.m_extraDistanceFront; UpdateRayPenetrationOnMove(oMotor, curRayFront, rayTransform.TransformPoint(curRayFront.m_position), oMotor.m_faceRight ? direction.right : direction.left); APCharacterMotor.CharacterRay2D curRayBack = new APCharacterMotor.CharacterRay2D(); curRayBack.m_position.x = oMotor.m_faceRight ? fOffsetX : fOffsetX + boxWidthX; curRayBack.m_position.y = curRayFront.m_position.y; curRayBack.m_extraDistance = oMotor.m_autoBuilder.m_extraDistanceBack; UpdateRayPenetrationOnMove(oMotor, curRayBack, rayTransform.TransformPoint(curRayBack.m_position), oMotor.m_faceRight ? direction.left : direction.right); raysFront[i] = curRayFront; raysBack[i] = curRayBack; } } oMotor.m_RaysUp = raysUp; oMotor.m_RaysGround = raysDown; oMotor.m_RaysFront = raysFront; oMotor.m_RaysBack = raysBack; // mark object as dirty EditorUtility.SetDirty(oMotor); } } }