Unity 在某平面随机点的方法

117 阅读1分钟
public class RandomPoint
{   
    /// <summary>
    /// 在矩形平面随机获取一个点
    /// </summary>
    /// <param name="axis">平面法线</param>
    /// <param name="size">矩形尺寸</param>
    /// <param name="center">矩形中心坐标,默认为0</param>
    /// <returns></returns>
    public static Vector3 GetRandomPointInRectangle(Vector3 axis,Vector2 size,Vector3 center = new Vector3())
    {
        Vector3[] orthogonalVectors = new[] { Vector3.right, Vector3.up, Vector3.forward };
        Vector3 axis1 = Vector3.zero;
        
        foreach (var orthogonal in orthogonalVectors)
        {
            axis1 = Vector3.Cross(axis, orthogonal).normalized;
            if (axis1.magnitude > 0)
            {
                break;
            }
        }

        Vector3 axis2 = Vector3.Cross(axis1, axis).normalized;

        // 随机生成矩形内的相对坐标
        float randomX = Random.Range(-size.x / 2f, size.x / 2f);
        float randomY = Random.Range(-size.y / 2f, size.y / 2f);

        // 计算全局坐标
        Vector3 randomPoint = center + axis1 * randomX + axis2 * randomY;
        return randomPoint;
    }
    
    /// <summary>
    /// 在圆面随机获取一个点
    /// </summary>
    /// <param name="axis">平面法线</param>
    /// <param name="radius">半径</param>
    /// <param name="center">圆心坐标,默认为0</param>
    /// <returns></returns>
    public static Vector3 GetRandomPointOnCircle(Vector3 axis, float radius, Vector3 center = new Vector3())
    {
        var dir = GetRandomVerticalVector(axis);
        var dis = Random.Range(0, radius);
        return dir * dis + center;
    }
    
    /// <summary>
    /// 在一个环形平面上随机获取一个点
    /// </summary>
    /// <param name="axis">平面法线 </param>
    /// <param name="inRadius">内圆半径</param>
    /// <param name="outRadius">外圆半径</param>
    /// <param name="center">圆心坐标,默认为0</param>
    /// <returns></returns>
    public static Vector3 GetRandomPointOnRing(Vector3 axis, float inRadius, float outRadius,
        Vector3 center = new Vector3())
    {
        var dir = GetRandomVerticalVector(axis);
        var dis = Random.Range(inRadius, outRadius);
        return dir * dis + center;
    }
    
    /// <summary>
    ///  获取一个随机垂直向量
    /// </summary>
    private static Vector3 GetRandomVerticalVector(Vector3 inputVector)
    {
        // 随机一个与输入向量不平行的向量
        Vector3 randomVector = GetRandomNonParallelVector(inputVector);

        // 计算与输入向量垂直的向量
        Vector3 perpendicularVector = Vector3.Cross(inputVector, randomVector);

        return perpendicularVector.normalized;
    }

    /// <summary>
    ///  生成一个与目标向量不平行的向量
    /// </summary>
    private static Vector3 GetRandomNonParallelVector(Vector3 inputAxis)
    {
        Vector3 randomVector;
        do
        {
            // 生成单位球体上的随机向量
            randomVector = Random.onUnitSphere;
        } while (Mathf.Abs(Vector3.Dot(randomVector, inputAxis.normalized)) > 0.99f);

        return randomVector;
    }
}