diff --git a/Assets/Main.unity b/Assets/Main.unity index f1a4b5d..05b83ae 100644 --- a/Assets/Main.unity +++ b/Assets/Main.unity @@ -288,6 +288,71 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 139439301} m_CullTransparentMesh: 1 +--- !u!1 &191862871 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 191862873} + - component: {fileID: 191862872} + m_Layer: 0 + m_Name: Traffic (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &191862872 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 191862871} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9bb25da9b61d4849b3c17eff30adbf8, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::TrafficLane + routeLength: 60 + laneCenter: 0 + vehiclePrefabs: + - {fileID: 1557020077158108179, guid: 7893264379c7b27449c0d5cd800de112, type: 3} + - {fileID: 6059035821173914762, guid: bf52a0f6f1d4ca94abedb85fa135a7cd, type: 3} + - {fileID: 7937761055385602081, guid: 692d27357d450044883464a7dc84418a, type: 3} + motorcyclePrefabs: [] + motorcycleRatio: 0 + motorcycleSpeedMultiplier: 1.3 + overtakeWidth: 0.5 + poolSize: 16 + baseSpeed: 6 + speedVariance: 0.05 + followDistance: 6 + safeGap: 2 + spawnInterval: 0.5 + spawnIntervalVariance: 0.4 + minSpawnGap: 4 + driftAmplitude: 0.05 + driftFrequency: 0.08 + lateralSmoothSpeed: 2 +--- !u!4 &191862873 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 191862871} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.24, y: 0, z: -23.145} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1527156285} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &203844586 GameObject: m_ObjectHideFlags: 0 @@ -1836,14 +1901,21 @@ MonoBehaviour: - {fileID: 1557020077158108179, guid: 7893264379c7b27449c0d5cd800de112, type: 3} - {fileID: 6059035821173914762, guid: bf52a0f6f1d4ca94abedb85fa135a7cd, type: 3} - {fileID: 7937761055385602081, guid: 692d27357d450044883464a7dc84418a, type: 3} - poolSize: 12 + motorcyclePrefabs: [] + motorcycleRatio: 0 + motorcycleSpeedMultiplier: 1.3 + overtakeWidth: 0.5 + poolSize: 16 baseSpeed: 6 speedVariance: 0.05 + followDistance: 6 + safeGap: 2 spawnInterval: 0.5 spawnIntervalVariance: 0.4 minSpawnGap: 4 driftAmplitude: 0.05 driftFrequency: 0.08 + lateralSmoothSpeed: 2 --- !u!4 &980030821 Transform: m_ObjectHideFlags: 0 @@ -1852,13 +1924,79 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 980030819} serializedVersion: 2 - m_LocalRotation: {x: 0, y: 1, z: 0, w: 0} - m_LocalPosition: {x: -0.28, y: 0, z: 37.23} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: -0.28, y: 0, z: 37.5} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 0} + m_Father: {fileID: 1527156285} m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!1 &1032635067 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1032635068} + - component: {fileID: 1032635069} + m_Layer: 0 + m_Name: Traffic w/ motor (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1032635068 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1032635067} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.71, y: 0, z: -23.03} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1527156285} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1032635069 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1032635067} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9bb25da9b61d4849b3c17eff30adbf8, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::TrafficLane + routeLength: 60 + laneCenter: 0 + vehiclePrefabs: + - {fileID: 1557020077158108179, guid: 7893264379c7b27449c0d5cd800de112, type: 3} + - {fileID: 6059035821173914762, guid: bf52a0f6f1d4ca94abedb85fa135a7cd, type: 3} + - {fileID: 7937761055385602081, guid: 692d27357d450044883464a7dc84418a, type: 3} + motorcyclePrefabs: + - {fileID: 6625968966535654452, guid: 446dfb1d91ecfcf41a2aaefc67e0a310, type: 3} + motorcycleRatio: 0.9 + motorcycleSpeedMultiplier: 1.3 + overtakeWidth: 0.2 + poolSize: 60 + baseSpeed: 4 + speedVariance: 0.05 + followDistance: 4 + safeGap: 2 + spawnInterval: 0.1 + spawnIntervalVariance: 0.4 + minSpawnGap: 1 + driftAmplitude: 0.2 + driftFrequency: 0.08 + lateralSmoothSpeed: 2 --- !u!1 &1142443635 GameObject: m_ObjectHideFlags: 0 @@ -2157,6 +2295,41 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1527156284 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1527156285} + m_Layer: 0 + m_Name: Traffics + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1527156285 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1527156284} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 980030821} + - {fileID: 1804377709} + - {fileID: 191862873} + - {fileID: 1032635068} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1553319431 GameObject: m_ObjectHideFlags: 0 @@ -2451,6 +2624,72 @@ Canvas: m_SortingLayerID: 0 m_SortingOrder: 0 m_TargetDisplay: 0 +--- !u!1 &1804377707 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1804377709} + - component: {fileID: 1804377708} + m_Layer: 0 + m_Name: Traffic w/ motor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1804377708 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1804377707} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9bb25da9b61d4849b3c17eff30adbf8, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::TrafficLane + routeLength: 60 + laneCenter: 0 + vehiclePrefabs: + - {fileID: 1557020077158108179, guid: 7893264379c7b27449c0d5cd800de112, type: 3} + - {fileID: 6059035821173914762, guid: bf52a0f6f1d4ca94abedb85fa135a7cd, type: 3} + - {fileID: 7937761055385602081, guid: 692d27357d450044883464a7dc84418a, type: 3} + motorcyclePrefabs: + - {fileID: 6625968966535654452, guid: 446dfb1d91ecfcf41a2aaefc67e0a310, type: 3} + motorcycleRatio: 0.9 + motorcycleSpeedMultiplier: 1.3 + overtakeWidth: 0.2 + poolSize: 60 + baseSpeed: 4 + speedVariance: 0.05 + followDistance: 4 + safeGap: 2 + spawnInterval: 0.1 + spawnIntervalVariance: 0.4 + minSpawnGap: 1 + driftAmplitude: 0.2 + driftFrequency: 0.08 + lateralSmoothSpeed: 2 +--- !u!4 &1804377709 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1804377707} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: -0.73, y: 0, z: 37.5} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1527156285} + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} --- !u!1 &1889754488 GameObject: m_ObjectHideFlags: 0 @@ -3908,6 +4147,6 @@ SceneRoots: - {fileID: 604712594} - {fileID: 505702790} - {fileID: 1142443636} - - {fileID: 980030821} + - {fileID: 1527156285} - {fileID: 465598214} - {fileID: 303688530} diff --git a/Assets/Scripts/Traffic/TrafficLane.cs b/Assets/Scripts/Traffic/TrafficLane.cs index efe6b05..5fb6737 100644 --- a/Assets/Scripts/Traffic/TrafficLane.cs +++ b/Assets/Scripts/Traffic/TrafficLane.cs @@ -4,12 +4,13 @@ using UnityEngine; /// /// Simulates a single lane of traffic by recycling a fixed pool of vehicle GameObjects. -/// Vehicles travel along local +Z, with organic lateral drift driven by Perlin noise. +/// Cars decelerate to maintain a safe following gap; motorcycles overtake by shifting sideways. +/// Vehicles travel along local +Z with organic Perlin-noise lateral drift. /// /// Usage: /// 1. Place this component on an empty GameObject aligned with the road lane. -/// 2. Assign vehicle prefabs, tune speed and drift. -/// 3. Duplicate and mirror-X for the opposite lane. +/// 2. Assign car / motorcycle prefabs, tune speed and drift. +/// 3. Duplicate and mirror-X (or rotate 180°) for the opposite lane. /// public class TrafficLane : MonoBehaviour { @@ -24,11 +25,28 @@ public class TrafficLane : MonoBehaviour // ── Vehicle Pool ────────────────────────────────────────────────────────── - [Header("Vehicle Pool")] - [Tooltip("Prefabs to randomly draw from when spawning. Can contain different vehicle types.")] + [Header("Cars")] + [Tooltip("Car prefabs — randomly chosen at spawn.")] [ListDrawerSettings(ShowFoldout = false)] public GameObject[] vehiclePrefabs; + [Header("Motorcycles")] + [Tooltip("Motorcycle prefabs — randomly chosen at spawn. Leave empty to disable motorcycles.")] + [ListDrawerSettings(ShowFoldout = false)] + public GameObject[] motorcyclePrefabs; + + [Tooltip("Fraction of pool slots assigned to motorcycles.")] + [Range(0f, 1f)] + public float motorcycleRatio = 0.2f; + + [Tooltip("Motorcycles travel this many times faster than baseSpeed on average.")] + [Range(1f, 2.5f)] + public float motorcycleSpeedMultiplier = 1.3f; + + [Tooltip("How far sideways (units) a motorcycle shifts when overtaking.")] + public float overtakeWidth = 0.5f; + + [Header("Pool")] [Tooltip("Total number of vehicle instances kept alive at once.")] [Range(1, 60)] public int poolSize = 12; @@ -39,9 +57,18 @@ public class TrafficLane : MonoBehaviour [Tooltip("Average forward speed in units / second.")] public float baseSpeed = 6f; - [Tooltip("Per-vehicle speed spread as a fraction of baseSpeed (±).")] + [Tooltip("Per-vehicle speed randomisation as a fraction of baseSpeed (±).")] [Range(0f, 0.5f)] - public float speedVariance = 0.2f; + public float speedVariance = 0.3f; + + // ── Following ───────────────────────────────────────────────────────────── + + [Header("Following")] + [Tooltip("Distance at which a vehicle starts reacting to the vehicle ahead.")] + public float followDistance = 8f; + + [Tooltip("Minimum comfortable gap. At this distance the follower matches the leader's speed exactly.")] + public float safeGap = 2f; // ── Spawn ───────────────────────────────────────────────────────────────── @@ -66,14 +93,25 @@ public class TrafficLane : MonoBehaviour [Range(0.01f, 1f)] public float driftFrequency = 0.08f; - // ── Private state ───────────────────────────────────────────────────────── + [Tooltip("How quickly vehicles adjust their lateral position (affects drift smoothness and overtake transitions).")] + [Range(0.5f, 10f)] + public float lateralSmoothSpeed = 2f; + + // ── Internals ───────────────────────────────────────────────────────────── + + private enum VehicleType { Car, Motorcycle } private class Agent { public GameObject go; - public float progress; // distance travelled along Z this trip - public float speed; // units / second for this trip - public float noiseRow; // unique Y coordinate in Perlin space for this trip + public VehicleType type; + public float progress; // distance travelled along Z this trip + public float targetSpeed; // natural cruising speed assigned at spawn + public float currentSpeed; // actual speed this frame (may be reduced by following) + public float noiseRow; // unique Y coordinate in Perlin space + public float currentLateral; // smoothed lateral X position + public bool overtaking; // motorcycle is currently overtaking + public float overtakeLateral; // lateral target while overtaking public bool active; } @@ -85,7 +123,7 @@ public class TrafficLane : MonoBehaviour private void Start() { - if (vehiclePrefabs == null || vehiclePrefabs.Length == 0) + if (!HasAnyPrefab()) { Debug.LogWarning("[TrafficLane] No vehicle prefabs assigned.", this); enabled = false; @@ -94,8 +132,6 @@ public class TrafficLane : MonoBehaviour BuildPool(); ScheduleNextSpawn(); - - // Scatter a few vehicles along the lane so it doesn't look empty at start. PrewarmLane(); } @@ -111,16 +147,28 @@ public class TrafficLane : MonoBehaviour { for (var i = 0; i < poolSize; i++) { - var prefab = vehiclePrefabs[Random.Range(0, vehiclePrefabs.Length)]; - var go = Instantiate(prefab, transform); + var isMotorcycle = HasMotorcyclePrefabs() && Random.value < motorcycleRatio; + var prefabs = PickPrefabArray(isMotorcycle); + if (prefabs == null || prefabs.Length == 0) + { + continue; + } + + var go = Instantiate(prefabs[Random.Range(0, prefabs.Length)], transform); go.SetActive(false); - pool.Add(new Agent { go = go, noiseRow = Random.Range(0f, 100f) }); + + pool.Add(new Agent + { + go = go, + type = isMotorcycle ? VehicleType.Motorcycle : VehicleType.Car, + noiseRow = Random.Range(0f, 100f), + currentLateral = laneCenter + }); } } private void PrewarmLane() { - // Spread inactive vehicles evenly so the lane looks populated from frame 1. var step = routeLength / Mathf.Max(poolSize * 0.5f, 1f); var z = Random.Range(0f, step); foreach (var agent in pool) @@ -145,7 +193,45 @@ public class TrafficLane : MonoBehaviour continue; } - agent.progress += agent.speed * Time.deltaTime; + FindLeader(agent, out var leaderGap, out var leaderSpeed, out var leaderLateral); + + var hasSlowerLeader = leaderGap < followDistance && + leaderSpeed < agent.targetSpeed * 0.98f; + + // ── Longitudinal speed ──────────────────────────────────────────── + + float effectiveSpeed; + + if (agent.type == VehicleType.Motorcycle && hasSlowerLeader) + { + // Motorcycle keeps speed and moves sideways to overtake. + effectiveSpeed = agent.targetSpeed; + agent.overtaking = true; + var side = leaderLateral >= laneCenter ? -1f : 1f; + agent.overtakeLateral = laneCenter + side * overtakeWidth; + } + else + { + // Car (or motorcycle with no slow leader ahead): follow and decelerate. + if (leaderGap < followDistance) + { + var t = Mathf.Clamp01( + (leaderGap - safeGap) / Mathf.Max(followDistance - safeGap, 0.01f)); + effectiveSpeed = Mathf.Lerp(leaderSpeed, agent.targetSpeed, t); + } + else + { + effectiveSpeed = agent.targetSpeed; + } + + if (agent.overtaking && leaderGap >= followDistance) + { + agent.overtaking = false; + } + } + + agent.currentSpeed = Mathf.Max(effectiveSpeed, 0f); + agent.progress += agent.currentSpeed * Time.deltaTime; if (agent.progress >= routeLength) { @@ -153,15 +239,28 @@ public class TrafficLane : MonoBehaviour continue; } - // Perlin noise: x-axis = position along route, y-axis = per-agent seed. - var noise = Mathf.PerlinNoise(agent.progress * driftFrequency, agent.noiseRow); - var lateral = laneCenter + (noise * 2f - 1f) * driftAmplitude; + // ── Lateral position ────────────────────────────────────────────── + + float targetLateral; + if (agent.overtaking) + { + targetLateral = agent.overtakeLateral; + } + else + { + var noise = Mathf.PerlinNoise(agent.progress * driftFrequency, agent.noiseRow); + targetLateral = laneCenter + (noise * 2f - 1f) * driftAmplitude; + } + + agent.currentLateral = Mathf.Lerp( + agent.currentLateral, targetLateral, Time.deltaTime * lateralSmoothSpeed); + + // ── Apply transform ─────────────────────────────────────────────── var prev = agent.go.transform.localPosition; - var next = new Vector3(lateral, 0f, agent.progress); + var next = new Vector3(agent.currentLateral, 0f, agent.progress); agent.go.transform.localPosition = next; - // Face direction of travel, ignoring tiny sub-frame deltas. var delta = next - prev; if (delta.sqrMagnitude > 1e-6f) { @@ -181,7 +280,6 @@ public class TrafficLane : MonoBehaviour spawnTimer = 0f; ScheduleNextSpawn(); - // Block spawn if another vehicle is still near the entry point. foreach (var agent in pool) { if (agent.active && agent.progress < minSpawnGap) @@ -195,27 +293,51 @@ public class TrafficLane : MonoBehaviour // ── Helpers ─────────────────────────────────────────────────────────────── - private void Activate(Agent agent, float startProgress) + private void FindLeader(Agent self, out float gap, out float speed, out float lateral) + { + gap = float.MaxValue; + speed = baseSpeed; + lateral = laneCenter; + + foreach (var other in pool) + { + if (!other.active || other == self) + { + continue; + } + var g = other.progress - self.progress; + if (g > 0f && g < gap) + { + gap = g; + speed = other.currentSpeed; + lateral = other.currentLateral; + } + } + } + + private void Activate(Agent agent, float startZ) { - agent.progress = startProgress; - agent.speed = baseSpeed * (1f + Random.Range(-speedVariance, speedVariance)); + var speedMult = agent.type == VehicleType.Motorcycle ? motorcycleSpeedMultiplier : 1f; + agent.progress = startZ; + agent.targetSpeed = baseSpeed * speedMult * (1f + Random.Range(-speedVariance, speedVariance)); + agent.currentSpeed = agent.targetSpeed; agent.noiseRow = Random.Range(0f, 100f); + agent.overtaking = false; + + var noise = Mathf.PerlinNoise(startZ * driftFrequency, agent.noiseRow); + agent.currentLateral = laneCenter + (noise * 2f - 1f) * driftAmplitude; + agent.go.transform.localPosition = new Vector3(agent.currentLateral, 0f, startZ); agent.go.SetActive(true); agent.active = true; - - // Teleport silently to start position before enabling. - var noise = Mathf.PerlinNoise(startProgress * driftFrequency, agent.noiseRow); - var lateral = laneCenter + (noise * 2f - 1f) * driftAmplitude; - agent.go.transform.localPosition = new Vector3(lateral, 0f, startProgress); } - private void SpawnNext(float startProgress) + private void SpawnNext(float startZ) { foreach (var agent in pool) { if (!agent.active) { - Activate(agent, startProgress); + Activate(agent, startZ); return; } } @@ -234,6 +356,26 @@ public class TrafficLane : MonoBehaviour nextSpawnDelay = Mathf.Max(0.1f, spawnInterval + Random.Range(-variance, variance)); } + private bool HasAnyPrefab() => + (vehiclePrefabs != null && vehiclePrefabs.Length > 0) || + (motorcyclePrefabs != null && motorcyclePrefabs.Length > 0); + + private bool HasMotorcyclePrefabs() => + motorcyclePrefabs != null && motorcyclePrefabs.Length > 0; + + private GameObject[] PickPrefabArray(bool motorcycle) + { + if (motorcycle && HasMotorcyclePrefabs()) + { + return motorcyclePrefabs; + } + if (vehiclePrefabs != null && vehiclePrefabs.Length > 0) + { + return vehiclePrefabs; + } + return motorcyclePrefabs; + } + // ── Editor visualisation ────────────────────────────────────────────────── #if UNITY_EDITOR @@ -245,18 +387,29 @@ public class TrafficLane : MonoBehaviour Gizmos.color = Color.yellow; Gizmos.DrawLine(start, end); - // Drift envelope. + // Drift envelope Gizmos.color = new Color(1f, 1f, 0f, 0.25f); - var left = transform.TransformPoint(new Vector3(laneCenter - driftAmplitude, 0f, 0f)); - var right = transform.TransformPoint(new Vector3(laneCenter + driftAmplitude, 0f, 0f)); - var leftEnd = transform.TransformPoint(new Vector3(laneCenter - driftAmplitude, 0f, routeLength)); - var rightEnd = transform.TransformPoint(new Vector3(laneCenter + driftAmplitude, 0f, routeLength)); - Gizmos.DrawLine(left, leftEnd); - Gizmos.DrawLine(right, rightEnd); - Gizmos.DrawLine(left, right); - Gizmos.DrawLine(leftEnd, rightEnd); - - // Entry / exit markers. + var ll = transform.TransformPoint(new Vector3(laneCenter - driftAmplitude, 0f, 0f)); + var rl = transform.TransformPoint(new Vector3(laneCenter + driftAmplitude, 0f, 0f)); + var lle = transform.TransformPoint(new Vector3(laneCenter - driftAmplitude, 0f, routeLength)); + var rle = transform.TransformPoint(new Vector3(laneCenter + driftAmplitude, 0f, routeLength)); + Gizmos.DrawLine(ll, lle); + Gizmos.DrawLine(rl, rle); + Gizmos.DrawLine(ll, rl); + Gizmos.DrawLine(lle, rle); + + // Overtake envelope (shown only when motorcycles are configured) + if (HasMotorcyclePrefabs() && motorcycleRatio > 0f) + { + Gizmos.color = new Color(0.4f, 0.8f, 1f, 0.15f); + var ml = transform.TransformPoint(new Vector3(laneCenter - overtakeWidth, 0f, 0f)); + var mr = transform.TransformPoint(new Vector3(laneCenter + overtakeWidth, 0f, 0f)); + var mle = transform.TransformPoint(new Vector3(laneCenter - overtakeWidth, 0f, routeLength)); + var mre = transform.TransformPoint(new Vector3(laneCenter + overtakeWidth, 0f, routeLength)); + Gizmos.DrawLine(ml, mle); + Gizmos.DrawLine(mr, mre); + } + Gizmos.color = Color.green; Gizmos.DrawSphere(start, 0.3f); Gizmos.color = Color.red; diff --git a/Assets/Settings/PC_RPAsset.asset b/Assets/Settings/PC_RPAsset.asset index f515bac..adca219 100644 --- a/Assets/Settings/PC_RPAsset.asset +++ b/Assets/Settings/PC_RPAsset.asset @@ -44,7 +44,7 @@ MonoBehaviour: m_ProbeVolumeSHBands: 1 m_MainLightRenderingMode: 1 m_MainLightShadowsSupported: 1 - m_MainLightShadowmapResolution: 2048 + m_MainLightShadowmapResolution: 8192 m_AdditionalLightsRenderingMode: 1 m_AdditionalLightsPerObjectLimit: 4 m_AdditionalLightShadowsSupported: 0 diff --git a/Assets/Temp/Motor.prefab b/Assets/Temp/Motor.prefab new file mode 100644 index 0000000..bdbc4e6 --- /dev/null +++ b/Assets/Temp/Motor.prefab @@ -0,0 +1,146 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1140205653522362818 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6935756313134080057} + - component: {fileID: 311920771717202595} + - component: {fileID: 7669487799238204824} + - component: {fileID: 8064391062658887605} + m_Layer: 0 + m_Name: Dummy + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6935756313134080057 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1140205653522362818} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.055, z: 0} + m_LocalScale: {x: 0.07, y: 0.11, z: 0.185} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7216495632142374776} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &311920771717202595 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1140205653522362818} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &7669487799238204824 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1140205653522362818} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!65 &8064391062658887605 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1140205653522362818} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!1 &6625968966535654452 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7216495632142374776} + m_Layer: 0 + m_Name: Motor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7216495632142374776 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6625968966535654452} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 6935756313134080057} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/Temp/Motor.prefab.meta b/Assets/Temp/Motor.prefab.meta new file mode 100644 index 0000000..cd810bd --- /dev/null +++ b/Assets/Temp/Motor.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 446dfb1d91ecfcf41a2aaefc67e0a310 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: