/// <summary> /// Check if the character controller top of the box with the /// slop calculation. /// </summary> /// <param name="cap"> character controller to test. </param> /// <param name="rect"> box to test. </param> /// <returns> /// true : is top of box. /// false : vice versa. /// </returns> public static bool TopOfBoxWithSlope(CharacterController cap, BoxCollider rect) { float innerAngle = rect.transform.localEulerAngles.z; // if no angle interact, just use the normal one. if (innerAngle == 0) { return(TopOfBox(cap, rect)); } /* Capsule */ Vector3 capScale = cap.transform.localScale; capScale = JCS_Mathf.AbsoluteValue(capScale); Vector3 cCenter = new Vector3( cap.center.x * capScale.x, cap.center.y * capScale.y, cap.center.z * capScale.z); Vector3 capCenterPos = cap.transform.position + cCenter; float cR = cap.radius * capScale.x; float cH = (cap.height - (cap.radius * 2.0f)) * capScale.y; // capsule botton point position. float cBotBound = cap.transform.position.y + cCenter.y - (cH / 2.0f) - cR; /* Box */ Vector3 rectScale = rect.transform.localScale; rectScale = JCS_Mathf.AbsoluteValue(rectScale); float rectWidth = rect.size.x * rectScale.x; float rectHeight = rect.size.y * rectScale.y; Vector3 rectCenter = new Vector3( rect.center.x * rectScale.x, rect.center.y * rectScale.y, rect.center.z * rectScale.z); Vector3 rectCenterPos = rect.transform.position + rectCenter; float radianInnerAngle = JCS_Mathf.DegreeToRadian(innerAngle); // at here 'rectHeight' are the same as 'adjacent'. // hyp = adj / cos(Θ) /* 斜角度的高度. */ float hypHeight = (rectHeight / Mathf.Cos(radianInnerAngle)) / 2; // 求'水平寬'. // adj = cos(Θ) * hyp float rectLeftToRight = Mathf.Cos(radianInnerAngle) * rectWidth; // 求'垂直高'. float rectTopAndBot = Mathf.Sin(radianInnerAngle) * rectWidth; float distRectLeftToCapCenter = JCS_Mathf.DistanceOfUnitVector( capCenterPos.x, rectCenterPos.x - (rectLeftToRight / 2)); /* Check if the capsule inside the the rect on x-axis. */ { float distCapToBox = JCS_Mathf.DistanceOfUnitVector( capCenterPos.x, rectCenterPos.x); if (distCapToBox > rectLeftToRight / 2) { return(false); } } float heightToCapBot = JCS_Mathf.CrossMultiply( rectLeftToRight, distRectLeftToCapCenter, rectTopAndBot); #if (UNITY_EDITOR) Debug.DrawLine( new Vector3( rectCenterPos.x - (rectLeftToRight / 2) + distRectLeftToCapCenter, rectCenterPos.y - (rectTopAndBot / 2), rectCenterPos.z), new Vector3( rectCenterPos.x - (rectLeftToRight / 2) + distRectLeftToCapCenter, rectCenterPos.y + heightToCapBot + hypHeight - (rectTopAndBot / 2), rectCenterPos.z), Color.cyan); #endif // 在平台上的點. float pointOnPlatform = rectCenterPos.y + heightToCapBot + hypHeight - (rectTopAndBot / 2); if (pointOnPlatform <= cBotBound) { return(true); } return(false); }
/// <summary> /// Set the box collider ontop of the other box collider /// with slop as a variable. /// </summary> /// <param name="setBox"> box we are setting on top of the other box </param> /// <param name="beSetBox"> box be under the setting box </param> /// <returns></returns> public static Vector3 SetOnTopOfBoxWithSlope(BoxCollider topBox, BoxCollider botBox, float offset = 0) { float innerAngle = botBox.transform.localEulerAngles.z; // if no angle interact, just use the normal one. if (innerAngle == 0) { return(SetOnTopOfBox(topBox, botBox)); } /* Top Box */ Vector3 topBoxScale = topBox.transform.localScale; topBoxScale = JCS_Mathf.AbsoluteValue(topBoxScale); Vector2 topBoxWH = GetColliderWidthHeight(topBox); Vector3 topBoxCenter = new Vector3( topBox.center.x * topBoxScale.x, topBox.center.y * topBoxScale.y, topBox.center.z * topBoxScale.z); Vector3 topBoxCenterPos = topBox.transform.position + topBoxCenter; /* Bot Box */ Vector3 rectScale = botBox.transform.localScale; rectScale = JCS_Mathf.AbsoluteValue(rectScale); float rectWidth = botBox.size.x * rectScale.x; float rectHeight = botBox.size.y * rectScale.y; Vector3 rectCenter = new Vector3( botBox.center.x * rectScale.x, botBox.center.y * rectScale.y, botBox.center.z * rectScale.z); Vector3 rectCenterPos = botBox.transform.position + rectCenter; float radianInnerAngle = JCS_Mathf.DegreeToRadian(innerAngle); // at here 'rectHeight' are the same as 'adjacent'. // hyp = adj / cos(Θ) /* 斜角度的高度. */ float hypHeight = (rectHeight / Mathf.Cos(radianInnerAngle)) / 2; // 求'水平寬'. // adj = cos(Θ) * hyp float rectLeftToRight = Mathf.Cos(radianInnerAngle) * rectWidth; // 求'垂直高'. float rectTopAndBot = Mathf.Sin(radianInnerAngle) * rectWidth; float distRectLeftToCapCenter = JCS_Mathf.DistanceOfUnitVector( topBoxCenterPos.x, rectCenterPos.x - (rectLeftToRight / 2)); /* Check if the capsule inside the the rect on x-axis. */ { float distCapToBox = JCS_Mathf.DistanceOfUnitVector( topBoxCenterPos.x, rectCenterPos.x); if (distCapToBox > rectLeftToRight / 2) { return(Vector3.zero); } } float heightToCapBot = JCS_Mathf.CrossMultiply( rectLeftToRight, distRectLeftToCapCenter, rectTopAndBot); #if (UNITY_EDITOR) Debug.DrawLine( new Vector3( rectCenterPos.x - (rectLeftToRight / 2) + distRectLeftToCapCenter, rectCenterPos.y - (rectTopAndBot / 2), rectCenterPos.z), new Vector3( rectCenterPos.x - (rectLeftToRight / 2) + distRectLeftToCapCenter, rectCenterPos.y + heightToCapBot + hypHeight - (rectTopAndBot / 2), rectCenterPos.z), Color.cyan); #endif // 在平台上的點. float pointOnPlatform = rectCenterPos.y + heightToCapBot + hypHeight - (rectTopAndBot / 2); /** ------------------------------------------- **/ Vector3 newPos = topBoxCenterPos; newPos.y = pointOnPlatform + (topBoxWH.y / 2); topBox.transform.position = newPos - topBoxCenter; return(newPos); }