一、框架視圖
二偷霉、關鍵代碼
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>
/// 日夜循環(huán)
/// </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;
}
}