美文网首页
VR开发实战HTC Vive项目之天气系统及智能交通

VR开发实战HTC Vive项目之天气系统及智能交通

作者: TonyWan_AR | 来源:发表于2020-02-25 17:43 被阅读0次

    一、框架视图

    二、关键代码

    EnviroZone

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    
    [AddComponentMenu("Enviro/Weather Zone")]
    public class EnviroZone : MonoBehaviour {
    
        public enum WeatherUpdateMode
        {
            GameTimeHours,
            RealTimeMinutes
        }
    
        [Tooltip("Defines the zone name.")]
        public string zoneName;
        [Tooltip("Uncheck to remove OnTriggerExit call when using overlapping zone layout.")]
        public bool ExitToDefault = true;
    
        public List<EnviroWeatherPrefab> zoneWeather = new List<EnviroWeatherPrefab>();
        public List<EnviroWeatherPrefab> curPossibleZoneWeather;
    
        [Header("Zone weather settings:")]
        [Tooltip("Add all weather prefabs for this zone here.")]
        public List<EnviroWeatherPreset> zoneWeatherPresets = new List<EnviroWeatherPreset>();
        [Tooltip("Shall weather changes occure based on gametime or realtime?")]
        public WeatherUpdateMode updateMode = WeatherUpdateMode.GameTimeHours;
        [Tooltip("Defines how often (gametime hours or realtime minutes) the system will heck to change the current weather conditions.")]
        public float WeatherUpdateIntervall = 6f;
        [Header("Zone scaling and gizmo:")]
        [Tooltip("Defines the zone scale.")]
        public Vector3 zoneScale = new Vector3 (100f, 100f, 100f);
        [Tooltip("Defines the color of the zone's gizmo in editor mode.")]
        public Color zoneGizmoColor = Color.gray;
    
        [Header("Current active weather:")]
        [Tooltip("The current active weather conditions.")]
        public EnviroWeatherPrefab currentActiveZoneWeatherPrefab;
        public EnviroWeatherPreset currentActiveZoneWeatherPreset;
        [HideInInspector]public EnviroWeatherPrefab lastActiveZoneWeatherPrefab;
        [HideInInspector]public EnviroWeatherPreset lastActiveZoneWeatherPreset;
    
        private BoxCollider zoneCollider;
        private double nextUpdate;
        private float nextUpdateRealtime;
        private bool init = false;
        private bool isDefault;
    
    
        void Start () 
        {
            if (zoneWeatherPresets.Count > 0)
            {
                zoneCollider = gameObject.AddComponent<BoxCollider> ();
                zoneCollider.isTrigger = true;
    
                if (!GetComponent<EnviroSky> ())
                    EnviroSky.instance.RegisterZone (this);
                else 
                    isDefault = true;
    
                UpdateZoneScale ();
                nextUpdate = EnviroSky.instance.currentTimeInHours + WeatherUpdateIntervall;
                nextUpdateRealtime = Time.time + (WeatherUpdateIntervall * 60f); 
            }
            else
            {
                Debug.LogError("Please add Weather Prefabs to Zone:" + gameObject.name);
            }
        }
    
        public void UpdateZoneScale ()
        {
            if (!isDefault)
                zoneCollider.size = zoneScale;
            else
                zoneCollider.size = (Vector3.one * (1f / EnviroSky.instance.transform.localScale.y)) * 0.25f;
        }
    
        public void CreateZoneWeatherTypeList ()
        {
            // Add new WeatherPrefabs
            for ( int i = 0; i < zoneWeatherPresets.Count; i++)
            {
                if (zoneWeatherPresets [i] == null) {
                    Debug.Log ("Warning! Missing Weather Preset in Zone: " + this.zoneName);
                    return;
                }
    
                bool addThis = true;
                for (int i2 = 0; i2 < EnviroSky.instance.Weather.weatherPresets.Count; i2++)
                {
                    if (zoneWeatherPresets [i] == EnviroSky.instance.Weather.weatherPresets [i2]) 
                    {
                        addThis = false;
                        zoneWeather.Add (EnviroSky.instance.Weather.WeatherPrefabs [i2]);
                    }
                }
    
                if (addThis) {
                    GameObject wPrefab = new GameObject ();
                    EnviroWeatherPrefab wP = wPrefab.AddComponent<EnviroWeatherPrefab> ();
                    wP.weatherPreset = zoneWeatherPresets [i];
                    wPrefab.name = wP.weatherPreset.Name;
    
                    // Check and create particle systems.
                    for (int w = 0; w < wP.weatherPreset.effectSystems.Count; w++)
                    {
                        if (wP.weatherPreset.effectSystems [w] == null || wP.weatherPreset.effectSystems [w].prefab == null) {
                            Debug.Log ("Warning! Missing Particle System Entry: " + wP.weatherPreset.Name);
                            Destroy (wPrefab);
                            return;
                        }
                        GameObject eS = (GameObject)Instantiate (wP.weatherPreset.effectSystems [w].prefab, wPrefab.transform);
                        eS.transform.localPosition = wP.weatherPreset.effectSystems [w].localPositionOffset;
                        eS.transform.localEulerAngles = wP.weatherPreset.effectSystems [w].localRotationOffset;
                        ParticleSystem pS = eS.GetComponent<ParticleSystem> ();
    
                        if (pS != null)
                            wP.effectSystems.Add (pS);
                        else {
                            pS = eS.GetComponentInChildren<ParticleSystem> ();
                            if (pS != null)
                                wP.effectSystems.Add (pS);
                            else {
                                Debug.Log ("No Particle System found in prefab in weather preset: " + wP.weatherPreset.Name);
                                Destroy (wPrefab);
                                return;
                            }
                        }
                    }
                    wP.effectEmmisionRates.Clear ();
                    wPrefab.transform.parent = EnviroSky.instance.Weather.VFXHolder.transform;
                    wPrefab.transform.localPosition = Vector3.zero;
                    wPrefab.transform.localRotation = Quaternion.identity;
                    zoneWeather.Add(wP);
    
                    EnviroSky.instance.Weather.WeatherPrefabs.Add (wP);
                    EnviroSky.instance.Weather.weatherPresets.Add (zoneWeatherPresets [i]);
                }
            }
            
            // Setup Particle Systems Emission Rates
            for (int i = 0; i < zoneWeather.Count; i++)
            {
                for (int i2 = 0; i2 < zoneWeather[i].effectSystems.Count; i2++)
                {
                    zoneWeather[i].effectEmmisionRates.Add(EnviroSky.GetEmissionRate(zoneWeather[i].effectSystems[i2]));
                    EnviroSky.SetEmissionRate(zoneWeather[i].effectSystems[i2],0f);
                }   
            }
                
            //Set initial weather
            if (isDefault && EnviroSky.instance.Weather.startWeatherPreset != null) 
            {
                EnviroSky.instance.SetWeatherOverwrite(EnviroSky.instance.Weather.startWeatherPreset);
    
                for (int i = 0; i < zoneWeather.Count; i++)
                {
                    if(zoneWeather[i].weatherPreset == EnviroSky.instance.Weather.startWeatherPreset)
                    {
                        currentActiveZoneWeatherPrefab = zoneWeather[i];
                        lastActiveZoneWeatherPrefab = zoneWeather[i];
                    }
                }
                currentActiveZoneWeatherPreset = EnviroSky.instance.Weather.startWeatherPreset;
                lastActiveZoneWeatherPreset = EnviroSky.instance.Weather.startWeatherPreset;
            } 
            else 
            {
                currentActiveZoneWeatherPrefab = zoneWeather [0];
                lastActiveZoneWeatherPrefab = zoneWeather [0];
                currentActiveZoneWeatherPreset = zoneWeatherPresets [0];
                lastActiveZoneWeatherPreset = zoneWeatherPresets [0];
            }
    
            nextUpdate = EnviroSky.instance.currentTimeInHours + WeatherUpdateIntervall;
        }
            
        void BuildNewWeatherList ()
        {
            curPossibleZoneWeather = new List<EnviroWeatherPrefab> ();
            for (int i = 0; i < zoneWeather.Count; i++) 
            {
                switch (EnviroSky.instance.Seasons.currentSeasons)
                {
                case EnviroSeasons.Seasons.Spring:
                    if (zoneWeather[i].weatherPreset.Spring)
                        curPossibleZoneWeather.Add(zoneWeather[i]);
                    break;
                case EnviroSeasons.Seasons.Summer:
                    if (zoneWeather[i].weatherPreset.Summer)
                        curPossibleZoneWeather.Add(zoneWeather[i]);
                    break;
                case EnviroSeasons.Seasons.Autumn:
                    if (zoneWeather[i].weatherPreset.Autumn)
                        curPossibleZoneWeather.Add(zoneWeather[i]);
                    break;
                case EnviroSeasons.Seasons.Winter:
                    if (zoneWeather[i].weatherPreset.winter)
                        curPossibleZoneWeather.Add(zoneWeather[i]);
                    break;
                }
            } 
        }
    
        EnviroWeatherPrefab PossibiltyCheck ()
        {
            List<EnviroWeatherPrefab> over = new List<EnviroWeatherPrefab> ();
    
            for (int i = 0 ; i < curPossibleZoneWeather.Count;i++)
            {
                int würfel = UnityEngine.Random.Range (0,100);
    
                if (EnviroSky.instance.Seasons.currentSeasons == EnviroSeasons.Seasons.Spring)
                {
                    if (würfel <= curPossibleZoneWeather[i].weatherPreset.possibiltyInSpring)
                        over.Add(curPossibleZoneWeather[i]);
                }else
                if (EnviroSky.instance.Seasons.currentSeasons == EnviroSeasons.Seasons.Summer)
                {
                        if (würfel <= curPossibleZoneWeather[i].weatherPreset.possibiltyInSummer)
                        over.Add(curPossibleZoneWeather[i]);
                }else
                if (EnviroSky.instance.Seasons.currentSeasons == EnviroSeasons.Seasons.Autumn)
                {
                            if (würfel <= curPossibleZoneWeather[i].weatherPreset.possibiltyInAutumn)
                        over.Add(curPossibleZoneWeather[i]);
                }else
                if (EnviroSky.instance.Seasons.currentSeasons == EnviroSeasons.Seasons.Winter)
                {
                                if (würfel <= curPossibleZoneWeather[i].weatherPreset.possibiltyInWinter)
                        over.Add(curPossibleZoneWeather[i]);
                }
            } 
    
            if (over.Count > 0)
            {       
                EnviroSky.instance.NotifyZoneWeatherChanged (over [0].weatherPreset, this);
                return over [0];
            }
            else
                return currentActiveZoneWeatherPrefab;
        }
            
        void WeatherUpdate ()
        {
            nextUpdate = EnviroSky.instance.currentTimeInHours + WeatherUpdateIntervall;
            nextUpdateRealtime = Time.time + (WeatherUpdateIntervall * 60f); 
    
            BuildNewWeatherList ();
    
            lastActiveZoneWeatherPrefab = currentActiveZoneWeatherPrefab;
            lastActiveZoneWeatherPreset = currentActiveZoneWeatherPreset;
            currentActiveZoneWeatherPrefab = PossibiltyCheck ();
            currentActiveZoneWeatherPreset = currentActiveZoneWeatherPrefab.weatherPreset;
            EnviroSky.instance.NotifyZoneWeatherChanged (currentActiveZoneWeatherPreset, this);
        }
    
        IEnumerator CreateWeatherListLate ()
        {
            yield return 0;
            CreateZoneWeatherTypeList ();
            init = true;
        }
    
        void LateUpdate () 
        {
            if (EnviroSky.instance == null)
            {
                Debug.Log("No EnviroSky instance found!");
                return;
            }
    
            if (EnviroSky.instance.started && !init) 
            {
                if (isDefault) {
                    CreateZoneWeatherTypeList ();          
                    init = true;
                } else
                    StartCoroutine (CreateWeatherListLate ());
            }
    
            if (updateMode == WeatherUpdateMode.GameTimeHours) {
                if (EnviroSky.instance.currentTimeInHours > nextUpdate && EnviroSky.instance.Weather.updateWeather && EnviroSky.instance.started)
                    WeatherUpdate ();
            } else {
                if (Time.time > nextUpdateRealtime && EnviroSky.instance.Weather.updateWeather && EnviroSky.instance.started)
                    WeatherUpdate ();
            }
    
            if (EnviroSky.instance.Player == null)
            {
                // Debug.Log("No Player Assigned in EnviroSky object!");
                return;
            }
    
            if (isDefault && init)                               
                zoneCollider.center = new Vector3(0f,(EnviroSky.instance.Player.transform.position.y-EnviroSky.instance.transform.position.y) / EnviroSky.instance.transform.lossyScale.y,0f);
        }
    
    
        /// Triggers
        void OnTriggerEnter (Collider col)
        {
            if (EnviroSky.instance == null)
                return;
    
            if (EnviroSky.instance.profile.weatherSettings.useTag) {
                if (col.gameObject.tag == EnviroSky.instance.gameObject.tag) {
                    EnviroSky.instance.Weather.currentActiveZone = this;
                    EnviroSky.instance.NotifyZoneChanged (this);
                }
            } else {
                if (col.gameObject.GetComponent<EnviroSky> ()) {
                    EnviroSky.instance.Weather.currentActiveZone = this;
                    EnviroSky.instance.NotifyZoneChanged (this);
                }
            }
        }
    
        void OnTriggerExit (Collider col)
        {
            if (ExitToDefault == false || EnviroSky.instance == null)
                return;
            
            if (EnviroSky.instance.profile.weatherSettings.useTag) {
                if (col.gameObject.tag == EnviroSky.instance.gameObject.tag) {
                    EnviroSky.instance.Weather.currentActiveZone = EnviroSky.instance.Weather.zones[0];
                    EnviroSky.instance.NotifyZoneChanged (EnviroSky.instance.Weather.zones[0]);
                }
            } else {
                if (col.gameObject.GetComponent<EnviroSky> ()) {
                    EnviroSky.instance.Weather.currentActiveZone = EnviroSky.instance.Weather.zones[0];
                    EnviroSky.instance.NotifyZoneChanged (EnviroSky.instance.Weather.zones[0]);
                }
            }
        }
    
    
        void OnDrawGizmos () 
        {
            Gizmos.color = zoneGizmoColor;
            Gizmos.DrawCube (transform.position, new Vector3(zoneScale.x,zoneScale.y,zoneScale.z));
        }
    }
    
    

    EnviroActionEvent

    using UnityEngine;
    using System.Collections;
    
    public class EnviroEvents : MonoBehaviour {
    
    
        [System.Serializable]
        public class EnviroActionEvent : UnityEngine.Events.UnityEvent
        {
    
        }
        //[Header("Time Events")]
        public EnviroActionEvent onHourPassedActions = new EnviroActionEvent();
        public EnviroActionEvent onDayPassedActions = new EnviroActionEvent();
        public EnviroActionEvent onYearPassedActions = new EnviroActionEvent();
        public EnviroActionEvent onWeatherChangedActions = new EnviroActionEvent();
        public EnviroActionEvent onSeasonChangedActions = new EnviroActionEvent();
        public EnviroActionEvent onNightActions = new EnviroActionEvent();
        public EnviroActionEvent onDayActions = new EnviroActionEvent();
        public EnviroActionEvent onZoneChangedActions = new EnviroActionEvent();
    
        void Start ()
        {
            EnviroSky.instance.OnHourPassed += () => HourPassed ();
            EnviroSky.instance.OnDayPassed += () => DayPassed ();
            EnviroSky.instance.OnYearPassed += () => YearPassed ();
            EnviroSky.instance.OnWeatherChanged += (EnviroWeatherPreset type) =>  WeatherChanged ();
            EnviroSky.instance.OnSeasonChanged += (EnviroSeasons.Seasons season) => SeasonsChanged ();
            EnviroSky.instance.OnNightTime += () => NightTime ();
            EnviroSky.instance.OnDayTime += () => DayTime ();
            EnviroSky.instance.OnZoneChanged += (EnviroZone zone) =>  ZoneChanged ();
        }
            
        private void HourPassed()
        {
            onHourPassedActions.Invoke();
        }
    
        private void DayPassed()
        {
            onDayPassedActions.Invoke();
        }
            
        private void YearPassed()
        {
            onYearPassedActions.Invoke();
        }
    
        private void WeatherChanged()
        {
            onWeatherChangedActions.Invoke();
        }
    
        private void SeasonsChanged()
        {
            onSeasonChangedActions.Invoke();
        }
    
        private void NightTime()
        {
            onNightActions.Invoke ();
        }
    
        private void DayTime()
        {
            onDayActions.Invoke ();
        }
    
        private void ZoneChanged()
        {
            onZoneChangedActions.Invoke ();
        }
    
    }
    
    

    DayNight

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    /// <summary>
    /// 日夜循环
    /// </summary>
    public class DayNight : MonoBehaviour 
    {
    
        //天时间
        int currentSecond ;
        int currentMinute ;
        int currentHour ;
    
        //恒星时间
        float solarTime ;
        float lunarTime ;
    
        bool isLoop;
    
        void Start()
        {
         
            isLoop = true;
        }
        // Update is called once per frame
        void Update()
        {
            //if (Input.GetMouseButtonDown(0))
            //{
            //    EnviroSky.instance.GameTime.ProgressTime = EnviroTime.TimeProgressMode.OneDay;
            //}
    
            currentSecond = EnviroSky.instance.GameTime.Seconds;
            currentMinute = EnviroSky.instance.GameTime.Minutes;
            currentHour = EnviroSky.instance.GameTime.Hours;
            // Debug.Log("currentHour::" + currentHour + "----currentMinute:" + currentMinute + "------currentSecond" + currentSecond);
    
            solarTime = EnviroSky.instance.GameTime.solarTime;
            lunarTime = EnviroSky.instance.GameTime.lunarTime;
    
           // Debug.Log(" 太阳solarTime::" + solarTime + " 月亮lunarTime::" + lunarTime);
    
            //if (Input.GetMouseButtonDown(1))
            //{
    
    
            //    isLoop = false;
            //}
    
    
            if (!isLoop)
            {
                if (solarTime > 0.85)
                {
                    EnviroSky.instance.GameTime.ProgressTime = EnviroTime.TimeProgressMode.None;
    
                }
            }
    
    
    
    
        }
    
        public void StartDayChangeNight()
        {
            isLoop = true;
            EnviroSky.instance.GameTime.ProgressTime = EnviroTime.TimeProgressMode.OneDay;
            Invoke("DelayStopRun", 5f);
            
        }
    
    
    
        private void DelayStopRun() {
    
            isLoop = false;
        }
    }
    
    
    
    

    Rain

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Rain : MonoBehaviour
    {
    
    
        private bool isShow;
    
        void Start()
        {
    
        }
    
    
        void Update()
        {
    
        }
    
        public void StartRain()
        {
            isShow = true;
            gameObject.SetActive(isShow);
        }
    
    
        public void StopRain() {
            gameObject.SetActive(false);
        }
    }
    
    

    Snow

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Snow : MonoBehaviour {
    
        private bool isShow;
    
        void Start()
        {
    
        }
    
    
        void Update()
        {
    
        }
    
        public void StartSnow()
        {
            isShow = true;
            gameObject.SetActive(isShow);
            gameObject.transform.GetChild(0).gameObject.SetActive(isShow);
            
        }
    
        public void StopSnow()
        {
            gameObject.transform.GetChild(0).gameObject.SetActive(false);
            gameObject.SetActive(false);
        }
    }
    
    

    Typhoon

    
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Typhoon : MonoBehaviour {
    
       
    
        void Start()
        {
    
        }
    
    
        void Update()
        {
    
        }
    
        public void StartTyphoon()
        {
          
            gameObject.SetActive(true);
            Invoke("StopTypoon", 15f);
            AudioManager.Instance.PlayMusic(8,false);
        }
    
       public  void StopTypoon() {
    
            gameObject.SetActive(false);
            AudioManager.Instance.StopSound();
        }
    
    
    
    }
    
    

    WeathercHandle

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class WeathercHandle : MonoBehaviour {
    
        public DayNight dayNight;
        public Snow snow;
        public Rain rain;
        public Typhoon typhoon;
    
        void Start () {
    
            EventCenter.AddListener<string>(EventDefine.WeatherBtn, WeathercManager);
        }
    
        private void WeathercManager(string weather)
        {
            switch (weather)
            {
                case Tags.DayNight:
                    dayNight.StartDayChangeNight();
                    snow.StopSnow();
                    rain.StopRain();
                    typhoon.StopTypoon();
                    EnviroSky.instance.ChangeWeather("Cloudy 3");
                    break;
                case Tags.SnowBtn:
                    snow.StartSnow();
                    rain.StopRain();
                    typhoon.StopTypoon();
                    EnviroSky.instance.ChangeWeather("Heavy Snow");
                    break;
                case Tags.Rain:
                    rain.StartRain();
                    snow.StopSnow();
                    typhoon.StopTypoon();
                    EnviroSky.instance.ChangeWeather("Heavy Rain");
                    break;
                case Tags.Typhoon:
                    typhoon.StartTyphoon();
                    snow.StopSnow();
                    rain.StopRain();
                    EnviroSky.instance.ChangeWeather("Storm VR");
                    break;
                default:
                    break;
            }
        }
    
    
    

    CarWalkPath

    using UnityEngine;
    using System.Collections.Generic;
    
    public class CarWalkPath : WalkPath
    {
        [Tooltip("Vehicle Speed / Скорость машины")] public float moveSpeed = 12.0f;
        [Tooltip("Vehicle Deseleration / Торможение машины")] public float speadDecrease = 2.0f;
        [Tooltip("Vehicle Acceleration / Ускорение автомобиля")] public float speadIncrease = 2.0f;
        [Tooltip("Distance to Car / Расстояние до автомобиля")] public float distanceToCar = 10.0f;
        [Tooltip("Distance to traffic lights / Расстояние до светофора")] public float distanceToSemaphore = 10.0f;
        [HideInInspector] [SerializeField] [Tooltip("Ignore pedestrian colliders? / Игнорировать коллайдеры пешеходов?")] private bool _ignorePeople = false;
        [Tooltip("Distance to the point / Расстояние до точки")] public float nextPointThreshold = 3;
        [Tooltip("Maximum rotation angle for braking / Максимальный угол поворота для притормаживания")] public float maxAngleToMoveBreak = 8.0f;
    
        private void Start()
        {
            if(_ignorePeople)
            {
                Physics.IgnoreLayerCollision(9, 8, true);  
            }                 
        }      
    
        public override void CreateSpawnPoints()
        {
            SpawnPoints = new SpawnPoint[points.GetLength(0)];
    
            for (int i = 0; i < points.GetLength(0); i++)
            {
                var startPoint = _forward[i] ? points[i, 0] : points[i, points.GetLength(1) - 1];
                var nextPoint = _forward[i] ? points[i, 2] : points[i, points.GetLength(1) - 3];
    
                SpawnPoints[i] = SpawnPoint.CarCreate(
                    string.Format("SpawnPoint (Path {0})", i + 1),
                    startPoint,
                    nextPoint,
                    lineSpacing,
                    i,
                    _forward[i],
                    this,
                    3f,
                    10f
                );
            }
        }
    
        public override void SpawnOnePeople(int w, bool forward)
        {
            List<GameObject> pfb = new List<GameObject>(walkingPrefabs);
    
            for (int i = pfb.Count - 1; i >= 0; i--)
            {
                if (pfb[i] == null)
                {
                    pfb.RemoveAt(i);
                }
            }
    
            walkingPrefabs = pfb.ToArray();
            int prefabNum = UnityEngine.Random.Range(0, walkingPrefabs.Length);
            var people = gameObject;
    
            if (!forward)
            {
                people = Instantiate(walkingPrefabs[prefabNum], points[w, pointLength[0] - 2], Quaternion.identity) as GameObject;
            }
            else
            {
                people = Instantiate(walkingPrefabs[prefabNum], points[w, 1], Quaternion.identity) as GameObject;
            }
    
            var movePath = people.AddComponent<MovePath>();
            var car = people.AddComponent<CarAIController>();
            CarInitialize(ref car);
    
            people.transform.parent = par.transform;
            movePath.walkPath = this;
    
            if (!forward)
            {
                movePath.InitStartPosition(w, pointLength[0] - 3, loopPath, forward);
                people.transform.LookAt(points[w, pointLength[0] - 3]);
            }
            else
            {
                movePath.InitStartPosition(w, 1, loopPath, forward);
                people.transform.LookAt(points[w, 2]);
            }
    
            movePath._walkPointThreshold = nextPointThreshold;
        }
    
        public override void SpawnPeople()
        {
            List<GameObject> pfb = new List<GameObject>(walkingPrefabs);
    
            for (int i = pfb.Count - 1; i >= 0; i--)
            {
                if (pfb[i] == null)
                {
                    pfb.RemoveAt(i);
                }
            }
    
            walkingPrefabs = pfb.ToArray();
    
            if (points == null) DrawCurved(false);
    
            if (par == null)
            {
                par = new GameObject();
                par.transform.parent = gameObject.transform;
                par.name = "walkingObjects";
            }
    
            int pathPointCount;
    
            if (!loopPath)
            {
                pathPointCount = pointLength[0] - 2;
            }
            else
            {
                pathPointCount = pointLength[0] - 1;
            }
    
            if (pathPointCount < 2) return;
    
            var pCount = loopPath ? pointLength[0] - 1 : pointLength[0] - 2;
    
            for (int wayIndex = 0; wayIndex < numberOfWays; wayIndex++)
            {
                _distances = new float[pCount];
    
                float pathLength = 0f;
    
                for (int i = 1; i < pCount; i++)
                {
                    Vector3 vector;
                    if (loopPath && i == pCount - 1)
                    {
                        vector = points[wayIndex, 1] - points[wayIndex, pCount];
                    }
                    else
                    {
                        vector = points[wayIndex, i + 1] - points[wayIndex, i];
                    }
    
                    pathLength += vector.magnitude;
                    _distances[i] = pathLength;
                }
    
                bool forward = false;
    
                switch (direction.ToString())
                {
                    case "Forward":
                        forward = true;
                        break;
                    case "Backward":
                        forward = false;
                        break;
                    case "HugLeft":
                        forward = (wayIndex + 2) % 2 == 0;
                        break;
                    case "HugRight":
                        forward = (wayIndex + 2) % 2 != 0;
                        break;
                    case "WeaveLeft":
                        forward = wayIndex != 1 && wayIndex != 2 && (wayIndex - 1) % 4 != 0 && (wayIndex - 2) % 4 != 0;
                        break;
                    case "WeaveRight":
                        forward = wayIndex == 1 || wayIndex == 2 || (wayIndex - 1) % 4 == 0 || (wayIndex - 2) % 4 == 0;
                        break;
                }
    
                int peopleCount = Mathf.FloorToInt((Density * pathLength) / _minimalObjectLength * 0.2f);
                float segmentLen = _minimalObjectLength + (pathLength - (peopleCount * _minimalObjectLength)) / peopleCount;
    
                int[] pickList = CommonUtils.GetRandomPrefabIndexes(peopleCount, ref walkingPrefabs);
    
                Vector3[] pointArray = new Vector3[_distances.Length];
    
                for (int i = 1; i < _distances.Length; i++)
                {
                    pointArray[i - 1] = points[wayIndex, i];
                }
    
                pointArray[_distances.Length - 1] = loopPath ? points[wayIndex, 1] : points[wayIndex, _distances.Length];
    
                for (int peopleIndex = 0; peopleIndex < peopleCount; peopleIndex++)
                {
                    var people = gameObject;
                    var randomShift = UnityEngine.Random.Range(-segmentLen / 3f, segmentLen / 3f) + (wayIndex * segmentLen);
                    var finalRandomDistance = (peopleIndex + 1) * segmentLen + randomShift;
    
                    var routePosition = GetRoutePosition(pointArray, finalRandomDistance, pCount, loopPath);
                    Vector3 or;
    
                    RaycastHit[] rrr = Physics.RaycastAll(or = new Vector3(routePosition.x, routePosition.y + 10000, routePosition.z), Vector3.down, Mathf.Infinity);
    
                    bool isSemaphore = false;
    
                    for (int i = 0; i < rrr.Length; i++)
                    {
                        if (rrr[i].collider.GetComponent<SemaphoreSimulator>() != null || rrr[i].collider.GetComponent<SemaphorePeople>() != null)
                        {
                            isSemaphore = true;
                        }
                    }
    
                    if (isSemaphore) continue;
    
                    float dist = 0;
                    int bestCandidate = 0;
    
                    rrr = Physics.RaycastAll(or = new Vector3(routePosition.x, routePosition.y + highToSpawn, routePosition.z), Vector3.down, Mathf.Infinity);
    
                    for (int i = 0; i < rrr.Length; i++)
                    {
                        if (dist < Vector3.Distance(rrr[0].point, or))
                        {
                            bestCandidate = i;
                            dist = Vector3.Distance(rrr[0].point, or);
                        }
                    }
    
                    if (rrr.Length > 0)
                    {
                        routePosition.y = rrr[bestCandidate].point.y;
                    }
    
                    people = Instantiate(walkingPrefabs[pickList[peopleIndex]], routePosition, Quaternion.identity) as GameObject;
    
                    var movePath = people.AddComponent<MovePath>();
                    var car = people.AddComponent<CarAIController>();
                    CarInitialize(ref car);
    
                    people.transform.parent = par.transform;
                    movePath.walkPath = this;
                    movePath._walkPointThreshold = nextPointThreshold;
    
                    movePath.InitStartPosition(wayIndex,
                        GetRoutePoint((peopleIndex + 1) * segmentLen + randomShift, wayIndex, pCount, forward, loopPath), loopPath, forward);
    
                    movePath.SetLookPosition();
    
                    if (people.GetComponent<AddTrailer>())
                    {
                        people.GetComponent<AddTrailer>().Init();
                    }
                }
            }
        }
    
        private void CarInitialize(ref CarAIController carAIController)
        {
            float speed = moveSpeed + Random.Range(moveSpeed * -0.15f, moveSpeed * 0.15f);
            speed = Mathf.Clamp(speed, 0, 15);
            carAIController.MOVE_SPEED = speed;
    
            carAIController.INCREASE = speadIncrease;
            carAIController.DECREASE = speadDecrease;
            carAIController.TO_CAR = distanceToCar;
            carAIController.TO_SEMAPHORE = distanceToSemaphore;
            carAIController.MaxAngle = maxAngleToMoveBreak;
        }
    }
    

    PeopleWalkPath

    using UnityEngine;
    using System.Collections.Generic;
    
    public enum AnimationState
    {
        idle1, walk, run
    }
    
    public class PeopleWalkPath : WalkPath
    {
        [Tooltip("Animation of the pedestrian at the start / Анимация пешехода при старте")] public AnimationState animationState = AnimationState.walk;
        [Range(0.0f, 5.0f)] [Tooltip("Offset from the line along the X axis / Смещение от линии по оси X")] public float randXPos = 0.1f;
        [Range(0.0f, 5.0f)] [Tooltip("Offset from the line along the Z axis / Смещение от линии по оси Z")] public float randZPos = 0.1f;
    
        [HideInInspector] [SerializeField] [Tooltip("Ignore the colliders of other pedestrians / Игнорировать коллайдеры других пешеходов?")] private bool _ignorePeople = false;
        [HideInInspector] [SerializeField] [Tooltip("Set your animation speed? / Установить свою скорость анимации?")] private bool _overrideDefaultAnimationMultiplier = true;
        [HideInInspector] [SerializeField] [Tooltip("Speed animation of walking / Скорость анимации ходьбы")] private float _customWalkAnimationMultiplier = 1.1f;
        [HideInInspector] [SerializeField] [Tooltip("Running animation speed / Скорость анимации бега")] private float _customRunAnimationMultiplier = 0.5f;
        private float nextPointThreshold = 1;
    
        [Tooltip("Walking speed / Скорость ходьбы")] public float walkSpeed = 1.2f;
        [Tooltip("Running speed / Скорость бега")] public float runSpeed = 3.0f;
        private float speedRotation = 15.0f;
        [Tooltip("Viewing Angle / Угол обзора")] public float viewAngle = 55.0f;
        [Tooltip("Radius of visibility / Радиус видимости")] public float viewRadius = 3.0f;
        [Tooltip("Distance to the pedestrian / Дистанция до пешехода")] public float distToPeople = 4.0f;
        [Tooltip("Layers of car, traffic light, pedestrians, player / Слои автомобиля, светофора, пешеходов, игрока")] public LayerMask targetMask = 3840;
        [HideInInspector] public LayerMask obstacleMask;
    
        private void Start()
        {
            if(_ignorePeople)
            {
                Physics.IgnoreLayerCollision(8, 8, true);  
            }                 
        }    
    
        public override void CreateSpawnPoints()
        {
            SpawnPoints = new SpawnPoint[points.GetLength(0)];
    
            for (int i = 0; i < points.GetLength(0); i++)
            {
                var startPoint = _forward[i] ? points[i, 0] : points[i, points.GetLength(1) - 1];
                var nextPoint = _forward[i] ? points[i, 2] : points[i, points.GetLength(1) - 3];
    
                SpawnPoints[i] = SpawnPoint.PeopleCreate(
                    string.Format("SpawnPoint (Path {0})", i + 1),
                    startPoint,
                    nextPoint,
                    lineSpacing,
                    i,
                    _forward[i],
                    this,
                    3f,
                    1f
                );
            }
        }
    
        public override void SpawnOnePeople(int w, bool forward)
        {
            List<GameObject> pfb = new List<GameObject>(walkingPrefabs);
    
            for (int i = pfb.Count - 1; i >= 0; i--)
            {
                if (pfb[i] == null)
                {
                    pfb.RemoveAt(i);
                }
            }
    
            walkingPrefabs = pfb.ToArray();
            int prefabNum = Random.Range(0, walkingPrefabs.Length);
            var people = gameObject;
    
            if (!forward)
            {
                people = Instantiate(walkingPrefabs[prefabNum], points[w, pointLength[0] - 2], Quaternion.identity) as GameObject;
            }
            else
            {
                people = Instantiate(walkingPrefabs[prefabNum], points[w, 1], Quaternion.identity) as GameObject;
            }
    
            var movePath = people.AddComponent<MovePath>();
            var passersby = people.AddComponent<Passersby>();
    
    
            movePath.randXFinish = Random.Range(-randXPos, randXPos);
            movePath.randZFinish = Random.Range(-randZPos, randZPos);
    
            InitializePassersby(ref passersby);
    
            people.transform.parent = par.transform;
            movePath.walkPath = this;
    
            if (!forward)
            {
                movePath.InitStartPosition(w, pointLength[0] - 3, loopPath, forward);
                people.transform.LookAt(points[w, pointLength[0] - 3]);
            }
            else
            {
                movePath.InitStartPosition(w, 1, loopPath, forward);
                people.transform.LookAt(points[w, 2]);
            }
    
            movePath._walkPointThreshold = nextPointThreshold;
        }
    
        public override void SpawnPeople()
        {
            List<GameObject> pfb = new List<GameObject>(walkingPrefabs);
    
            for (int i = pfb.Count - 1; i >= 0; i--)
            {
                if (pfb[i] == null)
                {
                    pfb.RemoveAt(i);
                }
            }
    
            walkingPrefabs = pfb.ToArray();
    
            if (points == null) DrawCurved(false);
    
            if (par == null)
            {
                par = new GameObject();
                par.transform.parent = gameObject.transform;
                par.name = "walkingObjects";
            }
    
            int pathPointCount;
    
            if (!loopPath)
            {
                pathPointCount = pointLength[0] - 2;
            }
            else
            {
                pathPointCount = pointLength[0] - 1;
            }
    
            if (pathPointCount < 2) return;
    
            var pCount = loopPath ? pointLength[0] - 1 : pointLength[0] - 2;
    
            for (int wayIndex = 0; wayIndex < numberOfWays; wayIndex++)
            {
                _distances = new float[pCount];
    
                float pathLength = 0f;
    
                for (int i = 1; i < pCount; i++)
                {
                    Vector3 vector;
                    if (loopPath && i == pCount - 1)
                    {
                        vector = points[wayIndex, 1] - points[wayIndex, pCount];
                    }
                    else
                    {
                        vector = points[wayIndex, i + 1] - points[wayIndex, i];
                    }
    
                    pathLength += vector.magnitude;
                    _distances[i] = pathLength;
                }
    
                bool forward = false;
    
                switch (direction.ToString())
                {
                    case "Forward":
                        forward = true;
                        break;
                    case "Backward":
                        forward = false;
                        break;
                    case "HugLeft":
                        forward = (wayIndex + 2) % 2 == 0;
                        break;
                    case "HugRight":
                        forward = (wayIndex + 2) % 2 != 0;
                        break;
                    case "WeaveLeft":
                        forward = wayIndex != 1 && wayIndex != 2 && (wayIndex - 1) % 4 != 0 && (wayIndex - 2) % 4 != 0;
                        break;
                    case "WeaveRight":
                        forward = wayIndex == 1 || wayIndex == 2 || (wayIndex - 1) % 4 == 0 || (wayIndex - 2) % 4 == 0;
                        break;
                }
    
                int peopleCount = Mathf.FloorToInt((Density * pathLength) / _minimalObjectLength);
                float segmentLen = _minimalObjectLength + (pathLength - (peopleCount * _minimalObjectLength)) / peopleCount;
    
                int[] pickList = CommonUtils.GetRandomPrefabIndexes(peopleCount, ref walkingPrefabs);
    
                Vector3[] pointArray = new Vector3[_distances.Length];
    
                for (int i = 1; i < _distances.Length; i++)
                {
                    pointArray[i - 1] = points[wayIndex, i];
                }
    
                pointArray[_distances.Length - 1] = loopPath ? points[wayIndex, 1] : points[wayIndex, _distances.Length];
    
                for (int peopleIndex = 0; peopleIndex < peopleCount; peopleIndex++)
                {
                    var people = gameObject;
                    var randomShift = Random.Range(-segmentLen / 3f, segmentLen / 3f) + (wayIndex * segmentLen);
                    var finalRandomDistance = (peopleIndex + 1) * segmentLen + randomShift;
    
                    Vector3 routePosition = GetRoutePosition(pointArray, finalRandomDistance, pCount, loopPath);
    
                    float XPos = Random.Range(-randXPos, randXPos);
                    float ZPos = Random.Range(-randZPos, randZPos);
    
                    routePosition = new Vector3(routePosition.x + XPos, routePosition.y, routePosition.z + ZPos);
                    Vector3 or;
    
                    RaycastHit[] rrr = Physics.RaycastAll(or = new Vector3(routePosition.x, routePosition.y + 10000, routePosition.z), Vector3.down, Mathf.Infinity);
    
                    bool isSemaphore = false;
    
                    for (int i = 0; i < rrr.Length; i++)
                    {
                        if (rrr[i].collider.GetComponent<SemaphoreSimulator>() != null || rrr[i].collider.GetComponent<SemaphorePeople>() != null)
                        {
                            isSemaphore = true;
                        }
                    }
    
                    if (isSemaphore) continue;
    
                    float dist = 0;
                    int bestCandidate = 0;
    
                    rrr = Physics.RaycastAll(or = new Vector3(routePosition.x, routePosition.y + highToSpawn, routePosition.z), Vector3.down, Mathf.Infinity);
    
                    for (int i = 0; i < rrr.Length; i++)
                    {
                        if (dist < Vector3.Distance(rrr[0].point, or))
                        {
                            bestCandidate = i;
                            dist = Vector3.Distance(rrr[0].point, or);
                        }
                    }
    
                    if (rrr.Length > 0)
                    {
                        routePosition.y = rrr[bestCandidate].point.y;
                    }
    
                    people = Instantiate(walkingPrefabs[pickList[peopleIndex]], routePosition, Quaternion.identity) as GameObject;
    
                    var movePath = people.AddComponent<MovePath>();
                    var passersby = people.AddComponent<Passersby>();
    
                    movePath.randXFinish = XPos;
                    movePath.randZFinish = ZPos;
    
                    InitializePassersby(ref passersby);
    
                    people.transform.parent = par.transform;
                    movePath.walkPath = this;
                    movePath._walkPointThreshold = nextPointThreshold;
    
                    movePath.InitStartPosition(wayIndex,
                        GetRoutePoint((peopleIndex + 1) * segmentLen + randomShift, wayIndex, pCount, forward, loopPath), loopPath, forward);
    
                    movePath.SetLookPosition();
                }
            }
        }
    
        private void InitializePassersby(ref Passersby _passersby)
        {
            _passersby.ANIMATION_STATE = animationState;
    
            _passersby.WALK_SPEED = walkSpeed;
            _passersby.RUN_SPEED = runSpeed;
            _passersby.SPEED_ROTATION = speedRotation;
    
            _passersby.VIEW_ANGLE = viewAngle;
            _passersby.VIEW_RADIUS = viewRadius;
            _passersby.targetMask = targetMask;
            _passersby.obstacleMask = obstacleMask;
            _passersby.DIST_TO_PEOPLE = distToPeople;
    
            _passersby.OverrideDefaultAnimationMultiplier = _overrideDefaultAnimationMultiplier;
            _passersby.CustomWalkAnimationMultiplier = _customWalkAnimationMultiplier;
            _passersby.CustomRunAnimationMultiplier = _customRunAnimationMultiplier;
        }
    }
    

    BcycleGyroPath

    using UnityEngine;
    using System.Collections.Generic;
    
    public class BcycleGyroPath : WalkPath
    {
        [Tooltip("Bicyclist Speed/ Скорость велосипедиста")] public float moveSpeed = 8.0f;
        [Tooltip("Acceleration / Ускорение")] public float increaseSpeed = 2.0f;
        [Tooltip("Braking / Торможение")] public float decreaseSpeed = 5.0f;
        [Range(0.1f, 5.0f)] [Tooltip("Offset from the line along the X axis / Смещение от линии по оси X")] public float randXPos = 0.1f;
        [Range(0.1f, 5.0f)] [Tooltip("Offset from the line along the Z axis / Смещение от линии по оси Z")] public float randZPos = 0.1f;
        [Tooltip("Скорость поворота")] public float speedRotation = 5.0f;
    
        [HideInInspector] [SerializeField] [Tooltip("Ignore pedestrian colliders? / Игнорировать коллайдеры пешеходов?")] private bool _ignorePeople = false;
        [HideInInspector] [SerializeField] [Tooltip("Customize your animation speed / Настроить свою скорость анимации?")] private bool _overrideDefaultAnimationMultiplier = true;
        [HideInInspector] [SerializeField] [Tooltip("Animation speed / Скорость анимации")] private float _customAnimationMultiplier = 2.0f;
        [Tooltip("Distance to next point / Расстояние до следующей точки")] public float nextPointThreshold = 3;
    
        private void Start()
        {
            if(_ignorePeople)
            {
                Physics.IgnoreLayerCollision(12, 8, true);  
            }                 
        }     
    
        public override void CreateSpawnPoints()
        {
            SpawnPoints = new SpawnPoint[points.GetLength(0)];
    
            for (int i = 0; i < points.GetLength(0); i++)
            {
                var startPoint = _forward[i] ? points[i, 0] : points[i, points.GetLength(1) - 1];
                var nextPoint = _forward[i] ? points[i, 2] : points[i, points.GetLength(1) - 3];
    
                SpawnPoints[i] = SpawnPoint.PeopleCreate(
                    string.Format("SpawnPoint (Path {0})", i + 1),
                    startPoint,
                    nextPoint,
                    lineSpacing,
                    i,
                    _forward[i],
                    this,
                    3f,
                    1f
                );
            }
        }
    
        public override void SpawnOnePeople(int w, bool forward)
        {
            List<GameObject> pfb = new List<GameObject>(walkingPrefabs);
    
            for (int i = pfb.Count - 1; i >= 0; i--)
            {
                if (pfb[i] == null)
                {
                    pfb.RemoveAt(i);
                }
            }
    
            walkingPrefabs = pfb.ToArray();
            int prefabNum = Random.Range(0, walkingPrefabs.Length);
            var people = gameObject;
    
            if (!forward)
            {
                people = Instantiate(walkingPrefabs[prefabNum], points[w, pointLength[0] - 2], Quaternion.identity) as GameObject;
            }
            else
            {
                people = Instantiate(walkingPrefabs[prefabNum], points[w, 1], Quaternion.identity) as GameObject;
            }
    
            var movePath = people.AddComponent<MovePath>();
            var controller = people.AddComponent<BcycleGyroController>();
    
            InitializeBcycleGyro(ref controller);
    
            movePath.randXFinish = Random.Range(-randXPos, randXPos);
            movePath.randZFinish = Random.Range(-randZPos, randZPos);
    
            people.transform.parent = par.transform;
            movePath.walkPath = this;
    
            if (!forward)
            {
                movePath.InitStartPosition(w, pointLength[0] - 3, loopPath, forward);
                people.transform.LookAt(points[w, pointLength[0] - 3]);
            }
            else
            {
                movePath.InitStartPosition(w, 1, loopPath, forward);
                people.transform.LookAt(points[w, 2]);
            }
    
            movePath._walkPointThreshold = nextPointThreshold;
        }
    
        public override void SpawnPeople()
        {
            List<GameObject> pfb = new List<GameObject>(walkingPrefabs);
    
            for (int i = pfb.Count - 1; i >= 0; i--)
            {
                if (pfb[i] == null)
                {
                    pfb.RemoveAt(i);
                }
            }
    
            walkingPrefabs = pfb.ToArray();
    
            if (points == null) DrawCurved(false);
    
            if (par == null)
            {
                par = new GameObject();
                par.transform.parent = gameObject.transform;
                par.name = "walkingObjects";
            }
    
            int pathPointCount;
    
            if (!loopPath)
            {
                pathPointCount = pointLength[0] - 2;
            }
            else
            {
                pathPointCount = pointLength[0] - 1;
            }
    
            if (pathPointCount < 2) return;
    
            var pCount = loopPath ? pointLength[0] - 1 : pointLength[0] - 2;
    
            for (int wayIndex = 0; wayIndex < numberOfWays; wayIndex++)
            {
                _distances = new float[pCount];
    
                float pathLength = 0f;
    
                for (int i = 1; i < pCount; i++)
                {
                    Vector3 vector;
                    if (loopPath && i == pCount - 1)
                    {
                        vector = points[wayIndex, 1] - points[wayIndex, pCount];
                    }
                    else
                    {
                        vector = points[wayIndex, i + 1] - points[wayIndex, i];
                    }
    
                    pathLength += vector.magnitude;
                    _distances[i] = pathLength;
                }
    
                bool forward = false;
    
                switch (direction.ToString())
                {
                    case "Forward":
                        forward = true;
                        break;
                    case "Backward":
                        forward = false;
                        break;
                    case "HugLeft":
                        forward = (wayIndex + 2) % 2 == 0;
                        break;
                    case "HugRight":
                        forward = (wayIndex + 2) % 2 != 0;
                        break;
                    case "WeaveLeft":
                        forward = wayIndex != 1 && wayIndex != 2 && (wayIndex - 1) % 4 != 0 && (wayIndex - 2) % 4 != 0;
                        break;
                    case "WeaveRight":
                        forward = wayIndex == 1 || wayIndex == 2 || (wayIndex - 1) % 4 == 0 || (wayIndex - 2) % 4 == 0;
                        break;
                }
    
                int peopleCount = Mathf.FloorToInt((Density * pathLength) / _minimalObjectLength);
                float segmentLen = _minimalObjectLength + (pathLength - (peopleCount * _minimalObjectLength)) / peopleCount;
    
                int[] pickList = CommonUtils.GetRandomPrefabIndexes(peopleCount, ref walkingPrefabs);
    
                Vector3[] pointArray = new Vector3[_distances.Length];
    
                for (int i = 1; i < _distances.Length; i++)
                {
                    pointArray[i - 1] = points[wayIndex, i];
                }
    
                pointArray[_distances.Length - 1] = loopPath ? points[wayIndex, 1] : points[wayIndex, _distances.Length];
    
                for (int peopleIndex = 0; peopleIndex < peopleCount; peopleIndex++)
                {
                    var people = gameObject;
                    var randomShift = Random.Range(-segmentLen / 3f, segmentLen / 3f) + (wayIndex * segmentLen);
                    var finalRandomDistance = (peopleIndex + 1) * segmentLen + randomShift;
    
                    Vector3 routePosition = GetRoutePosition(pointArray, finalRandomDistance, pCount, loopPath);
    
                    float XPos = Random.Range(-randXPos, randXPos);
                    float ZPos = Random.Range(-randZPos, randZPos);
    
                    routePosition = new Vector3(routePosition.x + XPos, routePosition.y, routePosition.z + ZPos);
                    Vector3 or;
    
                    RaycastHit[] rrr = Physics.RaycastAll(or = new Vector3(routePosition.x, routePosition.y + 10000, routePosition.z), Vector3.down, Mathf.Infinity);
    
                    bool isSemaphore = false;
    
                    for (int i = 0; i < rrr.Length; i++)
                    {
                        if (rrr[i].collider.GetComponent<SemaphoreSimulator>() != null || rrr[i].collider.GetComponent<SemaphorePeople>() != null)
                        {
                            isSemaphore = true;
                        }
                    }
    
                    if (isSemaphore) continue;
    
                    float dist = 0;
                    int bestCandidate = 0;
    
                    rrr = Physics.RaycastAll(or = new Vector3(routePosition.x, routePosition.y + highToSpawn, routePosition.z), Vector3.down, Mathf.Infinity);
    
                    for (int i = 0; i < rrr.Length; i++)
                    {
                        if (dist < Vector3.Distance(rrr[0].point, or))
                        {
                            bestCandidate = i;
                            dist = Vector3.Distance(rrr[0].point, or);
                        }
                    }
    
                    if (rrr.Length > 0)
                    {
                        routePosition.y = rrr[bestCandidate].point.y;
                    }
    
                    people = Instantiate(walkingPrefabs[pickList[peopleIndex]], routePosition, Quaternion.identity) as GameObject;
    
                    var movePath = people.AddComponent<MovePath>();
                    var controller = people.AddComponent<BcycleGyroController>();
    
                    InitializeBcycleGyro(ref controller);
    
                    movePath.randXFinish = XPos;
                    movePath.randZFinish = ZPos;
    
                    people.transform.parent = par.transform;
                    movePath.walkPath = this;
                    movePath._walkPointThreshold = nextPointThreshold;
    
                    movePath.InitStartPosition(wayIndex,
                        GetRoutePoint((peopleIndex + 1) * segmentLen + randomShift, wayIndex, pCount, forward, loopPath), loopPath, forward);
    
                    movePath.SetLookPosition();
                }
            }
        }
    
        private void InitializeBcycleGyro(ref BcycleGyroController _bcycleGyro)
        {
            float randMoveSpeed = moveSpeed + Random.Range(moveSpeed * -0.15f, moveSpeed * 0.15f);
    
            _bcycleGyro.moveSpeed = randMoveSpeed;
            _bcycleGyro.increaseSpeed = increaseSpeed;
            _bcycleGyro.decreaseSpeed = decreaseSpeed;
            _bcycleGyro.speedRotation = speedRotation;
    
            _bcycleGyro.OverrideDefaultAnimationMultiplier = _overrideDefaultAnimationMultiplier;
            _bcycleGyro.CustomAnimationMultiplier = _customAnimationMultiplier;
        }
    }
    

    三、效果展示

    相关文章

      网友评论

          本文标题:VR开发实战HTC Vive项目之天气系统及智能交通

          本文链接:https://www.haomeiwen.com/subject/tvrdactx.html