zoukankan      html  css  js  c++  java
  • Unity个人常用数学运算函数总结

    下面是个人在开发中编写的常用数学运算函数,具体的意义会在后面解释,废话不说,先上代码:

    注意一些具有方向的函数时建立在XZ平面上的计算。

    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Events;
    
    public class MathTools
    {
        /// <summary>
        /// 获取从起点到末点的固定点表路径-包含起点和末点,包含起点
        /// </summary>
        /// <param name="pointWay">路径点表,</param>
        /// <param name="space">点与点之间的距离</param>
        /// <returns></returns>
        public static List<Vector3> GetEqualySpacePoints(List<Vector3> pointWay, float space)
        {
            List<Vector3> points = new List<Vector3>();
            if (pointWay == null || pointWay.Count == 0) return points;
            Vector3 indexPoint = pointWay[0];
            float tempSpaceDistance = 0;
            points.Add(pointWay[0]);
            foreach (Vector3 point in pointWay)
            {
                while (indexPoint != point)
                {
                    Vector3 tempPoint = indexPoint;
                    indexPoint = Vector3.MoveTowards(indexPoint, point, 0.02f);
                    tempSpaceDistance += Vector3.Distance(tempPoint, indexPoint);
                    if (tempSpaceDistance >= space)
                    {
                        tempSpaceDistance = 0;
                        points.Add(indexPoint);
                    }
                }
            }
    
            return points;
        }
    
        /// <summary>
        /// 获取从起点到末点的固定点表路径-包含起点和末点,包含起点
        /// </summary>
        /// <param name="pointWay">路径点表</param>
        /// <param name="space">间隔距离</param>
        /// <returns></returns>
        public static List<Vector3> GetEqualySpacePointsQuickly(List<Vector3> pointWay,float space)
        {
            List<Vector3> points = new List<Vector3>();
    
            #region 移动索引点
            int index = 0;
            float offset = 0;
            #endregion
    
            float distance = 0;
            while (index < pointWay.Count - 1)
            {
                if (space <= 0) break;
    
                Vector3 indexPoint = pointWay[index] + (pointWay[index + 1] - pointWay[index]).normalized * offset;
                float dis = Vector3.Distance(indexPoint, pointWay[index + 1]);
                float tempDistance = dis + distance;
                if (tempDistance >= space)
                {
                    offset += (space - distance);
                    if (distance == 0&&offset!=0) points.Add(indexPoint);//此处offset==0说明发生了两个相邻的点重合的情况,所以相邻的后一个点不需要被加入表
                    distance = 0;
                }
                else
                {
                    distance = tempDistance;
                    if (offset != 0 || index == 0) points.Add(indexPoint);
                    offset = 0;
                    index += 1;
                }
            }
    
            return points;
        }
    
        /// <summary>
        /// 从一个点表中获取一个线性距离距离内的点,最后一点可以是截取的一个点
        /// </summary>
        /// <param name="pointWay"></param>
        /// <param name="distance"></param>
        /// <returns></returns>
        public static List<Vector3> GetDistancePoints(List<Vector3> pointWay,float distance)
        {
            List<Vector3> points = new List<Vector3>();
            float tDistance=0;
            for(int i = 0; i < pointWay.Count; i++)
            {
                if (points.Count == 0)
                {
                    points.Add(pointWay[0]);
                    continue;
                }
    
                float dis = Vector3.Distance(pointWay[i - 1], pointWay[i]);
                float tDis = tDistance + dis;
    
                if (tDis < distance)
                {
                    points.Add(pointWay[i]);
                    tDistance = tDis;
                }else if(tDis == distance)
                {
                    points.Add(pointWay[i]);
                    tDistance = tDis;
                    break;
                }else if(tDis > distance) //生成新的点,并添加到points
                {
                    Vector3 dir = pointWay[i] - pointWay[i - 1];
                    Vector3 newPoint = pointWay[i - 1] + dir.normalized * (distance - tDistance);
                    points.Add(newPoint);
                    tDistance = distance;
                    break;
                }
            }
            if (tDistance != distance) points = new List<Vector3>();
            return points;
        }
    
        ///// <summary>
        ///// 从一个点表中,砍掉从起点开始的一个线性距离范围的点
        ///// </summary>
        ///// <param name="pointWay"></param>
        ///// <param name="distance"></param>
        //public void CutDistancePoints(ref List<Vector3> pointWay,float distance)
        //{
        //    List<Vector3> points = new List<Vector3>();
        //    float tDistance = 0;
        //    while (tDistance < distance)
        //    {
    
        //    }
        //}
    
        /// <summary>
        /// 获取一个路径的线性长度
        /// </summary>
        /// <param name="pointWay"></param>
        /// <returns></returns>
        public static float GetPathLength(List<Vector3> pointWay)
        {
            float distance = 0;
            Vector3 tempPoint=Vector3.zero;
            if (pointWay.Count > 0) tempPoint = pointWay[0];
            foreach(Vector3 v in pointWay)
            {
                distance += Vector3.Distance(v, tempPoint);
                tempPoint = v;
            }
            return distance;
        }
    
        /// <summary>
        /// 获取一个线性布局的点集(1010101),点之间等距,靠中间布局,即当原子数量只有一个的时候,放在中间
        /// </summary>
        /// <param name="centerPos">中心位置</param>
        /// <param name="dir">布局方向</param>
        /// <param name="length">布局长度</param>
        /// <param name="count">原子数量</param>
        /// <returns></returns>
        public static List<Vector3> GetLineGridWithCenterPoints(Vector3 centerPos, Vector3 dir, float length, int count, UnityAction<Vector3> del = null)
        {
            List<Vector3> points = new List<Vector3>();
    
            float angleSpace = length / (count - 1);
            float firstAngle = length / 2;
    
            if (count == 1)
            {
                points.Add(centerPos);
    
                if (del != null) del(centerPos);
                return points;
            }
    
            for (int i = 0; i < count; i++)
            {
                Vector3 pos = centerPos + dir * (firstAngle - angleSpace * i);
                points.Add(pos);
                if (del != null) del(pos);
            }
            return points;
        }
    
        /// <summary>
        /// 获取一个扇形上的固定数量的点,坐标系为世界坐标
        /// 1010101010101
        /// </summary>
        /// <param name="count"></param>
        /// <param name="pos"></param>
        /// <param name="angel"></param>
        /// <param name="radius"></param>
        /// <param name="del"></param>
        /// <returns></returns>
        public static List<TransformGeoData> GetSectorStaticCountDatas(int count, Vector3 pos, float angel, float radius, UnityAction<TransformGeoData> del = null)
        {
            List<TransformGeoData> trans = new List<TransformGeoData>();
    
            //0101010
            float angleSpace = angel / (count - 1);
            float firstAngle = angel / 2;
            if (count == 1)
            {
                TransformGeoData transformGeoData = new TransformGeoData();
                transformGeoData.position = pos + Vector3.forward * radius;
                transformGeoData.rotation = Quaternion.Euler(0, 0, 0);
                if (del != null) del(transformGeoData);
                trans.Add(transformGeoData);
                return trans;
            }
    
            for (int i = 0; i < count; i++)
            {
                TransformGeoData transformGeoData = new TransformGeoData();
                transformGeoData.rotation = Quaternion.Euler(0, firstAngle - angleSpace * i, 0);
                transformGeoData.position = pos + (transformGeoData.rotation * Vector3.forward) * radius;
                if (del != null) del(transformGeoData);
                trans.Add(transformGeoData);
            }
    
            return trans;
    
        }
    
        /// <summary>
        /// 获取一个环上的点表,相邻点之间的距离相等
        /// </summary>
        /// <param name="centerPos"></param>
        /// <param name="radius"></param>
        /// <param name="count"></param>
        /// <param name="del"></param>
        /// <returns></returns>
        public static List<Vector3> GetRingStaticCountPoints(Vector3 centerPos, float radius, int count, Vector3 forward, UnityAction<Vector3> del = null)
        {
            List<Vector3> points = new List<Vector3>();
    
            float length = radius * Mathf.PI * 2;//获取圆圈周长
            if (count == 0) return points;
    
            float angle = 360f / count;
    
            for (int i = 0; i < count; i++)
            {
                Vector3 dir;
                if (i == 0)
                {
                    dir = forward;
                }
                else
                {
                    dir = Quaternion.Euler(0f, angle * i, 0f) * forward;
                }
                Vector3 pos = centerPos + dir * radius;
                if (del != null) del(pos);
                points.Add(pos);
            }
    
            return points;
        }
    
        /// <summary>
        /// 目标是否在扇形区域内(也可认为是锥形区域)
        /// </summary>
        /// <param name="centerPos">扇形中心</param>
        /// <param name="forward">中心方向</param>
        /// <param name="angle">角度范围</param>
        /// <param name="radius">半径</param>
        /// <param name="targetPos">目标位置</param>
        /// <returns></returns>
        public static bool InAngleRange(Vector3 centerPos, Vector3 forward, float angle, float radius, Vector3 targetPos)
        {
            Vector3 dir = targetPos - centerPos;
            float ang1 = Vector3.Angle(forward, dir);
            if (ang1 > Mathf.Abs(angle / 2)) return false;
            float dis1 = Vector3.Distance(targetPos, centerPos);
            if (dis1 > radius) return false;
            return true;
        }
    
        //public O GetNearstTransform<T,O>(T target,List<T> objs)
        //{
        //    O o=objs.Count>0?objs[0].GetComponent<O> 
    
        //    return default(O);
        //}
    }
    
    /// <summary>
    /// 一个Transfor的几何信息
    /// </summary>
    public struct TransformGeoData
    {
        public Vector3 position;
        public Quaternion rotation;
    }

    1.获取从起点到终点的固定点表路径,点与点之间的距离为space,并且如果末尾出现盈余,那么最后原来的终点将会被抛弃,

    GetEqualySpacePoints(List<Vector3> pointWay, float space)

    注意这里是点路径移动计算,因此并不是绝对精确

    2.获取一个线性布局的点集(1010101),点之间等距,靠中间布局,即当原子数量只有一个的时候,放在中间

    public static List<Vector3> GetLineGridWithCenterPoints(Vector3 centerPos,Vector3 dir,float length,int count,UnityAction<Vector3> del=null)

    其中del是可以在这个点进行一些操作,比如生成一个物体等,从而可以避免在获取这些点后进行第二次循环

    3.获取一个环上的点表,相邻点之间的距离相等

    public static List<Vector3> GetRingStaticCountPoints(Vector3 centerPos,float radius,int count,Vector3 forward,UnityAction<Vector3> del=null)

    其中forward的方向是当前的方向,这里的意义是,首先计算的第一个结果是以世界默认旋转为0计算的,然后在整体中心旋转到forward方向;或者可以理解为先以局部坐标获得结果,再转换为世界坐标方向。

    4.目标是否在扇形区域内(也可认为是锥形区域)

    public static bool InAngleRange(Vector3 centerPos,Vector3 forward,float angle,float radius,Vector3 targetPos)

     5.获取一个扇形上的固定数量的点,坐标系为世界坐标,这里没有做forwar处理,有兴趣的可以自己添加,即旋转叠加

    public static List<TransformGeoData> GetSectorStaticCountDatas(int count, Vector3 pos, float angel, float radius, UnityAction<TransformGeoData> del = null)

  • 相关阅读:
    eclipse 10个常用 快捷键
    struts2 s:set标签
    web项目的路径问题
    linux系统中用户切换
    java的多线程(一)
    Mongodb 与 Mongoose 的使用
    escape()、encodeURI()、encodeURIComponent()区别详解
    JSON WEB TOKEN
    关于使用REST API
    mac下设置mongodb开机启动方法
  • 原文地址:https://www.cnblogs.com/xiaoahui/p/13942509.html
Copyright © 2011-2022 走看看